﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using ZyGames.DZPocker.Model;
using ZyGames.DZPocker.Script.CsScript.Action;
using ZyGames.DZPocker.Tools;
using ZyGames.Framework.Cache.Generic;
using ZyGames.Framework.Common;
using ZyGames.Framework.Common.Log;
using ZyGames.Framework.Common.Serialization;
using ZyGames.Framework.Game.Cache;
using ZyGames.Framework.Net;

namespace ZyGames.DZPocker.Bll.Logic
{
	public enum ChipSettlementType : int
	{
		None = 0,
		AllIn,
		Fold,
	}

	/// <summary>
	/// 弃牌的结构
	/// </summary>
	public class GiveUp
	{
		/// <summary>
		/// 位置
		/// </summary>
		public int PosId;
		/// <summary>
		/// 筹码数量
		/// </summary>
		public int Chip;
	}

	public class GameEnd
	{
		/// <summary>
		/// 强退标记
		/// </summary>
		public int TotalEnd;

		/// <summary>
		/// 游戏税收
		/// </summary>
		public int[] GameTax = new int[GameTable.PlayerNum];
		/// <summary>
		/// 游戏得分
		/// </summary>
		public int[] GameScore = new int[GameTable.PlayerNum];
		/// <summary>
		/// 最后扑克
		/// </summary>
		public List<int[]> LastCenterCardData = new List<int[]>();
	}

	/// <summary>
	/// 游戏桌子管理
	/// </summary>
	public class GameTable
	{
		private static GameTable _instance;

		/// <summary>
		/// 玩家保存牌局锁
		/// </summary>
		static object userSavedTableLock = new object();
		/// <summary>
		/// 玩家上传头像锁
		/// </summary>
		static object userSavedHeadIcon = new object();

		//private VersionConfig _tableIdVersion;
		//private VersionConfig _userBetRecordIdVersion;
		//private VersionConfig _newUserBetRecordIdVersion;
		//private VersionConfig _gameTableCardsIdVersion;
		//private VersionConfig __gameTableUserHandCardsIdVersion;
		/// <summary>
		/// 玩家牌桌记录
		/// </summary>
		//public int NewTableId
		//{
		//	get { return _tableIdVersion.NextId; }
		//}

		//public int UserBetRecordId
		//{
		//	get { return _userBetRecordIdVersion.NextId; }
		//}

		//public int NewUserBetRecordId
		//{
		//	get { return _newUserBetRecordIdVersion.NextId; }
		//}

		//public int GameTableCardsId
		//{
		//	get { return _gameTableCardsIdVersion.NextId; }
		//}

		//public int GameTableUserHandsId
		//{
		//	get { return __gameTableUserHandCardsIdVersion.NextId; }
		//}

		public const int PlayerNum = 9;

		/// <summary>
		/// 断线事件
		/// </summary>
		public Action<int> OnDisconnectEvent;

		static GameTable()
		{
			_instance = new GameTable();
		}

		public static GameTable Current
		{
			get { return _instance; }
		}
		
		private CardRole _cardRole;
		private ShareCacheStruct<PokerInfo> _pokerConfig;
		private GameDataCacheSet<GameUser> _userCacheSet;
		private MemoryCacheStruct<RoomData> _roomStruct;

		private ShareCacheStruct<PhoneAndPwdInfo> phoneAndUserInfoCacheSet;


		//牌局战绩相关的记录

		//private GameDataCacheSet<UserAndTable> _userAndTableSet;
		//private GameDataCacheSet<UserBetRecord> _userBetRecordSet;

		/// <summary>
		/// 每一回合玩家的下注记录(只有玩家点击了保存才会保存到记录)
		/// </summary>
		//private GameDataCacheSet<NewUserBetRecord> _currentUserBetRecordSet;
		//private GameDataCacheSet<GameTableCards> _savedGameTableCardsSet;
		//private GameDataCacheSet<GameTableUserHandCards> _savedGameTableUserHandCardsSet;

		//private int userAndTableNextNo = 0;
		//private int userBetRecordNextNo = 0;
		//private int newUserBetRecordNextNo = 0;
		//public int tableCardsRecordNextNo = 0;
		//public int tableUserHandCardRecordNextNo = 0;

		/// <summary>
		/// 玩家申请保存的上句回顾的记录，前面是桌子的逻辑id，后面是第几手牌局和玩家的userid列表
		/// </summary>
		//private Dictionary<int, Dictionary<int, List<int>>> userSavedBetRecord;

		/// <summary>
		/// 被邀请加入牌桌的列表(tableId, <被邀请人,邀请人的userId>的列表)
		/// </summary>
		public Dictionary<int, Dictionary<int, int>> BeInvitedInfo;


		//************************牌桌的一些下注记录*************************************
		private GameDataCacheSet<GameTableData> _gameTableDataSet;
		/// <summary>
		/// 牌桌牌记录表
		/// </summary>
		private ShareCacheStruct<SharedGameTableCards> gameTableCardsCache;
		/// <summary>
		/// 玩家和牌桌记录表
		/// </summary>
		private ShareCacheStruct<SharedUserAndTable> userAndTableCache;
		/// <summary>
		/// 玩家下注记录表
		/// </summary>
		private ShareCacheStruct<SharedUserBetRecord> userBetRecordCache;
		/// <summary>
		/// 玩家每一手牌手牌表
		/// </summary>
		private ShareCacheStruct<SharedUserHandCards> userHandCardsCache;
		/// <summary>
		/// 玩家每一手牌盈亏记录表
		/// </summary>
		private ShareCacheStruct<SharedUserInTableHandScore> userHandScoreCache;
		/// <summary>
		/// 玩家保存牌桌记录表
		/// </summary>
		private ShareCacheStruct<SharedUserSaveTable> userSaveTableRecordCache;

		/// <summary>
		/// 玩家头像字节流列表
		/// </summary>
		private ShareCacheStruct<SharedUserHeadIcon> userHeadIconCache;

		private GameTable()
		{
			this._cardRole = new CardRole();
			this._pokerConfig = new ShareCacheStruct<PokerInfo>();
			this._userCacheSet = new GameDataCacheSet<GameUser>();
			//this._userCacheSet.ReLoad();
			this._roomStruct = new MemoryCacheStruct<RoomData>();
			//this._userAndTableSet = new GameDataCacheSet<UserAndTable>();
			//this._userAndTableSet.LoadFrom(i => i.TableID > 0);

			this._gameTableDataSet = new GameDataCacheSet<GameTableData>();
			//this._gameTableDataSet.ReLoad();
			this._gameTableDataSet.LoadFrom(i => i.TableID > 0);

			//this._userBetRecordSet = new GameDataCacheSet<UserBetRecord>();
			//this._userBetRecordSet.LoadFrom(i => i.ID > 0);
			this.OnDisconnectEvent = this.OnDisconnect;
			//this._tableIdVersion = new VersionConfig();
			//this._userBetRecordIdVersion = new VersionConfig();
			//_newUserBetRecordIdVersion = new VersionConfig();
			//_gameTableCardsIdVersion = new VersionConfig();
			//__gameTableUserHandCardsIdVersion = new VersionConfig();
			//this.userAndTableNextNo = this._userAndTableSet.ChildrenItem.Length;

			//this.userBetRecordNextNo = this._userBetRecordSet.ChildrenItem.Length;




			//加载所有的玩家下注记录
			//this._currentUserBetRecordSet = new GameDataCacheSet<NewUserBetRecord>();
			//this._currentUserBetRecordSet.LoadFrom(i => true);
			//this._savedGameTableCardsSet = new GameDataCacheSet<GameTableCards>();
			//this._savedGameTableCardsSet.LoadFrom(i => true);
			//this._savedGameTableUserHandCardsSet = new GameDataCacheSet<GameTableUserHandCards>();
			//this._savedGameTableUserHandCardsSet.LoadFrom(i => true);

			//this.newUserBetRecordNextNo = this._currentUserBetRecordSet.ChildrenItem.Length;
			//this.tableCardsRecordNextNo = this._savedGameTableCardsSet.ChildrenItem.Length;
			//this.tableUserHandCardRecordNextNo = this._savedGameTableUserHandCardsSet.ChildrenItem.Length;

			//userSavedBetRecord = new Dictionary<int, Dictionary<int, List<int>>>();
			BeInvitedInfo = new Dictionary<int, Dictionary<int, int>>();

			gameTableCardsCache = new ShareCacheStruct<SharedGameTableCards>();
			//gameTableCardsCache.Load();
			userAndTableCache = new ShareCacheStruct<SharedUserAndTable>();
			//userAndTableCache.Load();
			userBetRecordCache = new ShareCacheStruct<SharedUserBetRecord>();
			//userBetRecordCache.Load();
			userHandCardsCache = new ShareCacheStruct<SharedUserHandCards>();
			//userHandCardsCache.Load();
			userHandScoreCache = new ShareCacheStruct<SharedUserInTableHandScore>();
			//userHandScoreCache.Load();
			userSaveTableRecordCache = new ShareCacheStruct<SharedUserSaveTable>();
			//userSaveTableRecordCache.Load();
			phoneAndUserInfoCacheSet = new ShareCacheStruct<PhoneAndPwdInfo>();

			userHeadIconCache = new ShareCacheStruct<SharedUserHeadIcon>();
		}

		/// <summary>
		/// 添加账号密码
		/// </summary>
		/// <param name="phone"></param>
		/// <param name="pwd"></param>
		/// <returns></returns>
		public bool AddPhoneAndPwdInfo(string phone, string pwd)
		{
			var record = phoneAndUserInfoCacheSet.Find(i => i.PhoneNum == phone);
			if (record == null)
			{
				var res = phoneAndUserInfoCacheSet.Add(new PhoneAndPwdInfo() { PhoneNum = phone, Pwd = pwd });
				//phoneAndUserInfoCacheSet.Update();
				return res;
			}
			else
				return false;
		}

		public PhoneAndPwdInfo FindInfoByPhone(string phone)
		{
			return phoneAndUserInfoCacheSet.Find(i => i.PhoneNum == phone);
		}

		/// <summary>
		/// 判断手机号是否被注册过
		/// </summary>
		/// <param name="phone"></param>
		/// <returns></returns>
		public bool CheckPhoneIsRegisted(string phone)
		{
			var record = phoneAndUserInfoCacheSet.Find(i => i.PhoneNum == phone);
			return record != null;
		}

		private void ClearInviteRecordByTableId(int tableId)
		{
			Dictionary<int, int> tableValue;
			if (BeInvitedInfo.TryGetValue(tableId, out tableValue))
			{
				BeInvitedInfo.Remove(tableId);
			}
		}

		/// <summary>
		/// 获得所有被邀请人的信息
		/// </summary>
		/// <param name="beInvitedUserId"></param>
		public Dictionary<int, int> GetAllInvitesByBeInvitedUserId(int beInvitedUserId)
		{
			Dictionary<int, int> beInviteInfo = new Dictionary<int, int>();  //哪个桌子，邀请人
			foreach (var eachTable in BeInvitedInfo)
			{
				var tableId = eachTable.Key;
				var records = eachTable.Value;
				foreach (var playerInvite in records)
				{
					if (playerInvite.Key == beInvitedUserId)
					{
						beInviteInfo.Add(tableId, playerInvite.Value);
					}
				}
			}
			return beInviteInfo;
		}

		/// <summary>
		/// 点击叉号忽略邀请
		/// </summary>
		/// <param name="tableId"></param>
		/// <param name="inviteUserId"></param>
		/// <param name="beInvitedUserId"></param>
		/// <returns></returns>
		public bool DeleteInvite(int tableId, int inviteUserId, int beInvitedUserId)
		{
			Dictionary<int, int> tableValue;
			if (BeInvitedInfo.TryGetValue(tableId, out tableValue))
			{
				int inviteUID;
				if (tableValue.TryGetValue(beInvitedUserId, out inviteUID))
				{
					if (inviteUID != inviteUserId)
						return false;
					else
					{
						var res = tableValue.Remove(beInvitedUserId);
						if (!res)
							return res;
						else
						{
							if (tableValue.Count <= 0)
								BeInvitedInfo.Remove(tableId);
						}
						return true;
					}
				}
				else
					return false;
			}
			else
				return false;
		}

		/// <summary>
		/// 添加邀请入桌的信息
		/// </summary>
		/// <param name="tableId"></param>
		/// <param name="beInvitedUserId"></param>
		/// <param name="inviteUserId"></param>
		public bool AddBeInvitedUser(int tableId, int beInvitedUserId, int inviteUserId)
		{
			Dictionary<int, int> beInviteRecordInTable;
			if (BeInvitedInfo.TryGetValue(tableId, out beInviteRecordInTable))
			{
				if (!beInviteRecordInTable.ContainsKey(beInvitedUserId)) //之前这个牌桌没被邀请过
				{
					beInviteRecordInTable.Add(beInvitedUserId, inviteUserId);
				}
			}
			else
			{
				var record = new Dictionary<int, int>();
				record.Add(beInvitedUserId, inviteUserId);
				BeInvitedInfo.Add(tableId, record);
			}
			return true;
		}

		/// <summary>
		/// 游戏牌桌的编号
		/// </summary>
		/// <returns></returns>
		public int GetGameTableDataNextNo()
		{
			return (int)this._gameTableDataSet.GetNextNo();
		}

		/// <summary>
		/// 玩家是否可以保存上局回顾
		/// </summary>
		/// <param name="tableLogicId"></param>
		/// <param name="hand"></param>
		/// <param name="userId"></param>
		/// <returns></returns>
		public bool IsUserCanSaveBetRecord(int tableLogicId, int hand, int userId)
		{
			//var record = userSaveTableRecordCache.Find(i => (i.TableID == tableLogicId && i.UserID == userId && i.Hand == hand));
			var record = userSaveTableRecordCache.FindKey(tableLogicId, userId, hand);
			if (record != null)
			{
				Tool.WriteErrorLine("已经保存过");
				return false;
			}
			else
			{
				return true;
			}
		}

		/// <summary>
		/// 玩家已经保存牌谱的数量
		/// </summary>
		/// <param name="userid"></param>
		/// <returns></returns>
		public int UserSavedCount(int userid)
		{
			var records = userSaveTableRecordCache.FindAll((i) =>
			{
				if (i != null && i.UserID == userid)
					return true;
				else
					return false;
			});
			return records.Count;
		}

		/// <summary>
		/// 添加玩家保存上局回顾的记录
		/// </summary>
		/// <param name="tableLogicId"></param>
		/// <param name="hand"></param>
		/// <param name="userId"></param>
		/// <returns></returns>
		public bool AddUserSavedBetRecord(int tableLogicId, int hand, int userId)
		{
			bool res = false;
			lock (userSavedTableLock)
			{
				res = userSaveTableRecordCache.Add(new SharedUserSaveTable() { TableID = tableLogicId, UserID = userId, Hand = hand });
				//if (res)
				//	userSaveTableRecordCache.Update();
				//else
				//{
				//	Console.WriteLine("保存牌谱出错");
				//}
			}
			
			return res;
		}

		/// <summary>
		/// 添加玩家头像
		/// </summary>
		/// <param name="userId"></param>
		/// <param name="headIconStr"></param>
		/// <returns></returns>
		public bool AddUserHeadIcon(int userId, string headIconStr)
		{
			bool res = false;
			lock(userSavedHeadIcon)
			{
				var headIconRecord = userHeadIconCache.FindKey(userId);
				if (headIconRecord == null)
				{
					res = userHeadIconCache.Add(new SharedUserHeadIcon() { UserID = userId, HeadIcon = headIconStr });
					//if (res)
					//	userHeadIconCache.Update();
				}
				else
				{
					userHeadIconCache.Delete(headIconRecord);
					res = userHeadIconCache.Add(new SharedUserHeadIcon() { UserID = userId, HeadIcon = headIconStr });
					//if (res)
					//	userHeadIconCache.Update();
				}
			}
			return res;
		}

		/// <summary>
		/// 获得玩家的头像
		/// </summary>
		/// <param name="userId"></param>
		/// <returns></returns>
		public string GetUserHeadIconByUserId(int userId)
		{
			var headIconRecord = userHeadIconCache.FindKey(userId);
			if (headIconRecord == null)
				return string.Empty;
			else
				return headIconRecord.HeadIcon;
		}

		/// <summary>
		/// 修改玩家的头像
		/// </summary>
		/// <param name="userId"></param>
		/// <param name="headIconStr"></param>
		/// <returns></returns>
		public bool ChangeUserHeadIcon(int userId, string headIconStr)
		{
			bool res = false;
			lock(userSavedHeadIcon)
			{
				var headIconRecord = userHeadIconCache.FindKey(userId);
				userHeadIconCache.Delete(headIconRecord);
				res = userHeadIconCache.Add(new SharedUserHeadIcon() { UserID = userId, HeadIcon = headIconStr });
				//if (res)
				//	userHeadIconCache.Update();
			}
			return res;
		}

		public List<SharedGameTableCards> ShredGameTableCardsByTableID(int tableId)
		{
			return gameTableCardsCache.FindAll((i) =>
			{
				if (i != null && i.TableID == tableId)
					return true;
				else
					return false;
			});
		}

		public List<SharedUserSaveTable> SharedUserSavedTable(int userid)
		{
			return userSaveTableRecordCache.FindAll((i) =>
			{
				if (i != null && i.UserID == userid)
					return true;
				else
					return false;
			});
		}

		public SharedUserInTableHandScore GetScoreInTableHand(int userId, int tableId, int hand)
		{
			//return userHandScoreCache.Find(i => (i.UserID == userId && i.TableID == tableId && i.Hand == hand));
			return userHandScoreCache.FindKey(userId, tableId, hand);
		}

		//这个变量是每次重启的话 都是会从1开始递增，1,2,3这样一次下去
		//public int GetUserAndTableNextNo()
		//{
		//	return (int)this._userAndTableSet.GetNextNo();
		//}

		//public int GetUserBetRecordNextNo()
		//{
		//	return (int)this._userBetRecordSet.GetNextNo();
		//}

		/// <summary>
		/// 点击保存牌谱
		/// </summary>
		/// <param name="record"></param>
		/// <returns></returns>
		//public bool SaveUserBetRecult(int userid, int hand, List<NewUserBetRecord> records)
		//{
		//	if (userid == 0)
		//	{
		//		Console.WriteLine("谁保存的牌谱没有指名");
		//		return false;
		//	}
		//	if (records == null)
		//	{
		//		Console.WriteLine("牌谱记录不存在");
		//		return false;
		//	}
		//	if (records.Count <= 0)
		//	{
		//		Console.WriteLine("牌谱数量不对");
		//		return false;
		//	}
		//	foreach (var record in records)
		//	{
		//		NewUserBetRecord newRecord = new NewUserBetRecord();
		//		newRecord.ID = this.newUserBetRecordNextNo + NewUserBetRecordId;
		//		newRecord.SavedByUserId = userid;
		//		newRecord.TableID = record.TableID;
		//		newRecord.Hand = hand;
		//		newRecord.UserID = record.UserID;
		//		newRecord.UserName = record.UserName;
		//		newRecord.UserHeadIcon = record.UserHeadIcon;
		//		newRecord.BetType = record.BetType;
		//		newRecord.BetNum = record.BetNum;
		//		newRecord.Round = record.Round;
		//		if (!this._currentUserBetRecordSet.Add(newRecord))
		//		{
		//			Console.WriteLine("保存牌谱下注记录报错");
		//			return false;
		//		}
		//	}
		//	this._currentUserBetRecordSet.Update();
		//	return true;
		//}

		/// <summary>
		/// 保存玩家桌面牌局
		/// </summary>
		/// <param name="userId"></param>
		/// <param name="table"></param>
		/// <param name="tableCards"></param>
		/// <returns></returns>
		//public bool SaveGameTableCards(int userId, int hand, GameTableCards tableCards)
		//{
		//	if (userId == 0)
		//	{
		//		Tool.WriteErrorLine("玩家Id不存在, 不能保存牌桌上的牌");
		//		return false;
		//	}
		//	if (tableCards == null)
		//	{
		//		Tool.WriteErrorLine("桌子上的牌不存在，不能保存");
		//		return false;
		//	}
		//	tableCards.ID = this.tableCardsRecordNextNo + this.GameTableCardsId;
		//	tableCards.Hand = hand;
		//	if (!this._savedGameTableCardsSet.Add(tableCards))
		//	{
		//		Tool.WriteErrorLine("添加牌桌上的牌记录错误");
		//		return false;
		//	}
		//	this._savedGameTableCardsSet.Update();
		//	return true;
		//}

		//public bool SaveGameTableUserHandCards(int userId, int hand, List<GameTableUserHandCards> userHandCards)
		//{
		//	if (userId == 0)
		//	{
		//		Tool.WriteErrorLine("玩家Id不存在, 不能保存牌桌上的牌");
		//		return false;
		//	}
		//	if (userHandCards == null || userHandCards.Count <= 0)
		//	{
		//		Tool.WriteErrorLine("玩家的牌不存在，不能保存");
		//		return false;
		//	}
		//	foreach (var userCards in userHandCards)
		//	{
		//		GameTableUserHandCards newUserHandCards = new GameTableUserHandCards();
		//		newUserHandCards.ID = this.GameTableUserHandsId + this.tableUserHandCardRecordNextNo;
		//		newUserHandCards.SavedUserID = userId;
		//		newUserHandCards.TableID = userCards.TableID;
		//		newUserHandCards.Hand = hand;
		//		newUserHandCards.UserID = userCards.UserID;
		//		newUserHandCards.UserNickName = userCards.UserNickName;
		//		newUserHandCards.UserHeadIcon = userCards.UserHeadIcon;
		//		newUserHandCards.Card0 = userCards.Card0;
		//		newUserHandCards.Card1 = userCards.Card1;
		//		newUserHandCards.WinChip = userCards.WinChip;
		//		if (!this._savedGameTableUserHandCardsSet.Add(newUserHandCards))
		//		{
		//			Tool.WriteErrorLine("添加玩家手牌出错");
		//			return false;
		//		}
		//	}
		//	this._savedGameTableUserHandCardsSet.Update();
		//	return true;
		//}

		/// <summary>
		/// 添加一个游戏桌子记录
		/// </summary>
		/// <param name="createTime"></param>
		/// <param name="gameOverTime"></param>
		private bool AddGameTableData(GameTableData table)
		{
			this._gameTableDataSet.Add(table);
			//this._gameTableDataSet.Update();
			return true;
		}

		public GameTableData GetGameTableData(int tableId)
		{
			return this._gameTableDataSet.FindKey(tableId.ToString());
		}

		/// <summary>
		/// 添加玩家所在的牌桌记录
		/// </summary>
		/// <param name="userId"></param>
		/// <param name="tableId"></param>
		/// <param name="profit"></param>
		/// <returns></returns>
		//private bool AddUserAndTable(UserAndTable userAndTable)
		//{
		//	this._userAndTableSet.Add(new UserAndTable(userAndTable.ID, userAndTable.UserID, userAndTable.TableID, userAndTable.Profit, userAndTable.IsMaster, userAndTable.NickName, userAndTable.HeadIcon));
		//	this._userAndTableSet.Update();
		//	return true;
		//}

		/// <summary>
		/// 获得玩家所在的牌桌记录
		/// </summary>
		/// <param name="userId"></param>
		/// <returns></returns>
		public List<SharedUserAndTable> GetUserTableByUserId(int userId)
		{
			return this.userAndTableCache.FindAll(i => i.UserID == userId);
		}
		/// <summary>
		/// 根据桌子id搜相关的记录
		/// </summary>
		/// <param name="tableId"></param>
		/// <returns></returns>
		public List<SharedUserAndTable> GetUserTableByTableId(int tableId)
		{
			return this.userAndTableCache.FindAll(i => i.TableID == tableId);
		}

		/// <summary>
		/// 获得玩家所在的牌桌记录
		/// </summary>
		/// <param name="userId"></param>
		/// <returns></returns>
		//public List<UserAndTable> GetUsersTablesByUserId(int userId)
		//{
		//	return this._userAndTableSet.FindGlobal(i => i.UserID == userId);
		//}

		/// <summary>
		/// 通过牌桌id获得玩家所在的牌桌记录
		/// </summary>
		/// <param name="tableId"></param>
		/// <returns></returns>
		//public List<UserAndTable> GetUserTablesByTableId(int tableId)
		//{
		//	return this._userAndTableSet.FindGlobal(i => i.TableID == tableId);
		//}

		/// <summary>
		/// 添加玩家下注记录
		/// </summary>
		/// <param name="userId"></param>
		/// <param name="tableId"></param>
		/// <param name="betType">下注类型</param>
		/// <param name="betNum">下注筹码数量</param>
		/// <returns></returns>
		//private bool AddGameUserBetRecord(UserBetRecord record)
		//{
		//	this._userBetRecordSet.Add(new UserBetRecord(record.ID, record.UserID, record.TableID, record.BetType, record.BetNum));
		//	this._userBetRecordSet.Update();
		//	return true;
		//}

		/// <summary>
		/// 获得一个桌子的所有玩家下注记录
		/// </summary>
		/// <param name="tableId"></param>
		/// <returns></returns>
		//private List<UserBetRecord> GetUserBetRecordByTableId(int tableId)
		//{
		//	return this._userBetRecordSet.FindGlobal(i => i.TableID == tableId);
		//}

		public List<PokerInfo> PokerList
		{
			get
			{
				return _pokerConfig.FindAll();
			}
		}

		/// <summary>
		/// 操作倒计时
		/// </summary>
		public int CodeTime
		{
			get
			{
				return ConfigEnvSet.GetInt("User.TableCodeTime", 10);
			}
		}

		/// <summary>
		/// 获得RoomData
		/// </summary>
		/// <param name="roomId"></param>
		/// <returns></returns>
		private RoomData GetRoomData(int roomId)
		{
			string key = roomId.ToString();
			RoomData roomData;
			if (_roomStruct.TryGet(key, out roomData))
			{
				return roomData;
			}
			return null;
		}

		/// <summary>
		/// 获取玩家座位
		/// </summary>
		/// <param name="user"></param>
		/// <param name="tableData"></param>
		/// <returns></returns>
		public PositionData GetUserPosition(GameUser user, TableData tableData)
		{
			return GetUserPosition(user.Property.GetPositionId(tableData.TableId), tableData);
		}

		public PositionData GetUserPosition(int positionId, TableData tableData)
		{
			if (positionId < tableData.Positions.Length)
			{
				PositionData pos = tableData.Positions[positionId - 1];
				return pos;
			}
			return null;
		}

		/// <summary>
		/// 创建一副牌数据
		/// </summary>
		/// <param name="tableData"></param>
		/// <param name="pokers"></param>
		private void CreateCardData(TableData tableData, List<PokerInfo> pokers)
		{
			if (pokers == null) throw new ArgumentNullException("pokers");
			foreach (var pokerInfo in pokers)
			{
				tableData.CardData.Add(pokerInfo.Id);
			}
		}

		/// <summary>
		/// 随机取牌
		/// </summary>
		/// <param name="cardData"></param>
		/// <param name="timeNum">次数</param>
		/// <returns></returns>
		private void ShuffleCard(List<int> cardData, int timeNum = 0)
		{
			int count = cardData.Count;
			int randCount = 0;
			int index = 0;
			int endIndex = 0;
			int temp = 0;
			int val = 0;
			do
			{
				int endPos = count - randCount;
				if (endPos <= 0)
				{
					break;
				}
				index = RandomUtils.GetRandom(0, endPos);
				endIndex = endPos - 1;
				if (endIndex == index)
				{
					//自己与自己不替换
					randCount++;
					continue;
				}
				temp = cardData[endIndex];
				val = cardData[index];
				cardData[endIndex] = val;
				cardData[index] = temp;
				randCount++;
			} while (randCount < count && (timeNum == 0 || randCount < timeNum));
		}

		/// <summary>
		/// 设置最后五张牌为底牌
		/// </summary>
		/// <param name="tableData"></param>
		/// <param name="backNum">最后的底牌数量</param>
		private void SetBackCard(TableData tableData, int backNum = 5)
		{
			int index = tableData.CardData.Count - backNum;
			var list = tableData.CardData.GetRange(index, backNum);
			if (list.Count > 0)
			{
				tableData.BackCardData.AddRange(list);
			}
		}

		/// <summary>
		/// 发牌，每个玩家只会发两张牌
		/// </summary>
		/// <param name="tableData"></param>
		/// <param name="backNum"></param> 
		private void SendCard(TableData tableData, int backNum)
		{
			//洗牌
			ShuffleCard(tableData.CardData);

			//设置一副牌的备份
			tableData.BackUpCardData.Clear();
			tableData.BackUpCardData.AddRange(tableData.CardData);

			//设置五张底牌
			SetBackCard(tableData, backNum);

			var cardData = tableData.CardData;
			//牌的数量
			int cardCount = cardData.Count - backNum;  //去除最顶上的五张牌
			//当前已经坐下的座位
			var playStatePosition = tableData.CurrentPlayingPositionData;
			var posCount = playStatePosition.Count;
			for (int i = 0; i < posCount; i++)
			{
				int posIndex = i;
				var position = tableData.CurrentPlayingPositionData[posIndex];
				//只有有人坐下并且是准备就绪状态才飞位置发牌
				if (position.Ready())
				{
					if (position.CardData.Count > 0)
					{
						position.ReSendCard();
					}
					//将牌添加进每个座位的的手牌列表,每个玩家只会获得两张牌
					int times = 0;
					for (int j = posIndex; j < cardCount; j = j + posCount)
					{
						position.CardData.Add(cardData[j]);
						tableData.BackUpCardData.Remove(cardData[j]);
						if (++times >= 2)
							break;
					}
				}
			}
		}

		/// <summary> 
		/// 随机选择一个桌子
		/// </summary>
		/// <param name="user"></param>
		/// <param name="roomData"></param>
		/// <param name="roomInfo">房间配置</param>
		/// <returns></returns>
		public TableData CreateTable(GameUser user, RoomData roomData, RoomInfo roomInfo)
		{
			var pockers = PokerList;
			//生成桌子号码和邀请码
			int tableId = roomData.NewTableId;
			//生成不重复的六位数字邀请码
			var inviteNum = this.GenerateInviteNum(roomData);
			var userTable = new TableData(
				tableId,
				inviteNum,
				roomInfo.PlayerNum,
				DoTableTimer,
				roomData.RoomId);

			CreateCardData(userTable, pockers);

			if (userTable != null)
			{
				EnterTable(roomData.RoomId, userTable, user);
				roomData.Tables.Add(userTable.TableId, userTable);
			}
			return userTable;
		}

		/// <summary>
		/// 判断邀请码是否存在
		/// </summary>
		/// <param name="room"></param>
		/// <param name="num">桌子邀请码</param>
		/// <returns></returns>
		private bool ContainsInviteNum(RoomData room, int num)
		{
			foreach (var pair in room.Tables)
			{
				var tableData = pair.Value;
				if (tableData.InviteNum == num)
				{
					return false;
				}
			}
			return true;
		}

		/// <summary>
		/// 生成六位数的随机码
		/// </summary>
		private int GenerateInviteNum(RoomData room)
		{
			Random rand = new Random(Guid.NewGuid().GetHashCode());
			int inviteNum = 0;

			while (inviteNum < 99999 || ContainsInviteNum(room, inviteNum) == false)
			{
				inviteNum = rand.Next(1000000);
			}
			return inviteNum;
		}

		public bool JoinTable(GameUser user, TableData table, RoomData roomData)
		{
			TableData tableData;
			if (!roomData.Tables.TryGetValue(table.TableId, out tableData))
			{
				return false;
			}
			if (tableData == null || tableData.TableId != table.TableId)
			{
				return false;
			}
			return EnterTable(roomData.RoomId, table, user);
		}

		/// <summary>
		/// 进入桌子
		/// </summary>
		/// <param name="roomId"></param>
		/// <param name="table"></param>
		/// <param name="user"></param>
		private bool EnterTable(int roomId, TableData table, GameUser user)
		{
			if (!table.PlayersData.Contains(user))
			{
				table.PlayersData.Add(user);
				user.Property.InitTableInfo(roomId, table.TableId);
				return true;
			}
			else
			{
				Console.WriteLine("已经包含了一个玩家");
				return false;
			}
		}

		//桌子的定时器事件方法
		private void DoTableTimer(object state)
		{
			try
			{
				if (state is TableData)
				{
					Console.WriteLine("*****************************进入定时器");
					var temp = state as TableData;
					TableData table;
					RoomData roomData = GetRoomData(temp.RoomId);
					if (!roomData.Tables.TryGetValue(temp.TableId, out table))
					{
						return;
					}
					if (table.State == TableState.WaitCheck)
					{
						table.StopTimer();
						Tool.WriteErrorLine("2S可以退出的时间到");
						CheckStartCallBack(table);
						return;
					}
					//3s倒计时
					if (table.State == TableState.Countdown)
					{
						table.StopTimer();
						Tool.WriteErrorLine("倒计时时间到");
						table.State = TableState.Waiting;
						this.StartGame(table);
						return;
					}
					if (table.State == TableState.Insurance)
					{
						table.StopTimer();
						Tool.WriteErrorLine("保险操作时间到");
						//记录已经改变的玩家ＩＤ
						List<int> changedList = new List<int>();
						foreach (var r in table.CurrentRoundBuyInsuranceUsersID)
						{
							if (!r.Value)
							{
								var uid = r.Key;
								for (int i = 0; i < table.InsurancePool.Count; i++)
								{
									var pool = table.InsurancePool[i];
									if (pool.MaxUserId == uid)
										pool.CurrentRoundIsOperated = true;
								}
								changedList.Add(uid);
								var param = new Parameters();
								param["TableId"] = table.TableId;
								param["UserId"] = uid;
								var player = GetUser(uid);
								if (player != null)
								{
									Tool.WriteErrorLine("取消保险协议30029");
									//取消保险协议
									SyncNotifyAction((int)ActionType.DZPassivCancelInsurance, player, param, t =>
									{
										Tool.WriteWarmingLine(string.Format("广播消息30029取消保险"));
									});
								}
							}
						}
						if (changedList.Count > 0)
						{
							foreach (var id in changedList)
							{
								table.CurrentRoundBuyInsuranceUsersID[id] = true;
							}
						}

						table.State = TableState.Playing;
						this.RoundInsuranceOperate(table);
						return;
					}
					//押注时间到，判断是看牌或者说弃牌强制发送对应消息给玩家
					var currentPos = table.GetCurrentPosition();
					if (currentPos == null)
					{
						Tool.WriteErrorLine("获得当前位置不存在");
						return;
					}
					//客户端已经主动下注过了,停止定时器
					if (!currentPos.BetState)
					{
						Console.WriteLine(string.Format("当前桌子{0}位置{1}已经下过注", table.TableId, currentPos.Id));
						table.StopTimer();
						return;
					}
					bool fold = false;
					//自动看牌
					if (table.CurrentMaxChip == 0)
					{
						currentPos.PlayState = PositionPlayState.Look;
					}
					//自动弃牌   TODO:弃牌之后要检测是否游戏结束
					else
					{
						currentPos.PlayState = PositionPlayState.Fold;
						fold = true;
					}
					this.OnUserBet(table, table.TableId, 0, currentPos);
					if (fold)
					{
						OnUserGiveUp(table, currentPos.Id);
					}
					else
					{
						Tool.WriteErrorLine("**************************自动下注");
						currentPos.BetState = false;
						table.StopTimer();
						this.NextBet(table);
						//table.DoTimeNumber();
					}
					//table.StopTimer();
				}
			}
			catch (Exception ex)
			{
				TraceLog.WriteError("Timer error:{0}", ex.ToString());
			}
		}

		/// <summary>
		/// 随机选择一个座位
		/// </summary>
		/// <param name="user"></param>
		/// <param name="roomData"></param>
		/// <param name="table"></param>
		/// <returns></returns>
		private bool SelectPosition(GameUser user, RoomData roomData, TableData table)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// 离开座位
		/// </summary>
		/// <param name="user"></param>
		/// <param name="table"></param>
		public void ExitTablePosition(GameUser user, TableData table)
		{
			//如果逃跑
			if (table.IsFlee)
			{
				return;
			}
			foreach (var pos in table.Positions)
			{
				if (pos.Id == user.Property.GetPositionId(table.TableId))
				{
					CheckFlee(user, table, pos);
					break;
				}
			}
		}

		/// <summary>
		/// 检查是否逃跑
		/// </summary>
		/// <param name="user"></param>
		/// <param name="table"></param>
		/// <param name="pos"></param>
		private void CheckFlee(GameUser user, TableData table, PositionData pos)
		{
			throw new NotImplementedException();
		}

		/// <summary>
		/// 回合结束将所有个人筹码添加进底池
		/// </summary>
		/// <param name="table"></param>
		public void CollectChip(TableData table)
		{
			int ant = 0;
			var userBeats = new List<UserBeat>();
			foreach (var pos in table.CurrentPlayingPositionData)
			{
				if (pos.CurrentRoundChip > 0)
				{
					ant += pos.CurrentRoundChip;
					userBeats.Add(new UserBeat() { Chip = pos.CurrentRoundChip, PosId = pos.Id, UserId = pos.UserId });
					pos.CurrentRoundChip = 0;
				}
			}
			var userBeatsInfo = Convert.ToBase64String(ProtoBufUtils.Serialize(userBeats));
			var ChipParam = new Parameters();
			ChipParam["TableID"] = table.TableId;
			ChipParam["UserBeats"] = userBeatsInfo;
			table.AnteNum += ant;
			SyncNotifyAction((int)ActionType.DZBrocastChipIntoAntNum, table, ChipParam, t =>
			{
				Console.WriteLine("广播30015 通知将玩家的下注筹码添加进底池 桌子:{0}", table.TableId);
			});
			System.Threading.Thread.Sleep(800);
			//同步底池和玩家筹码的数量
			this.SyncAllChip(table);
		}


		/// <summary>
		/// 获得玩家的牌组的类型
		/// </summary>
		/// <param name="positionData"></param>
		private void GetUserCardType(List<PositionData> positionData)
		{
			foreach (var pos in positionData)
			{
				var cardsize = new int[5];
				var deckType = this._cardRole.GetCardType(pos.CardData.ToArray(), out cardsize);
				pos.CardsDeckType = deckType;
				pos.CardsValue = cardsize;
			}
		}

		/// <summary>
		/// 同步所有的相关记录
		/// </summary>
		/// <param name="table"></param>
		private void SyncGameTableData(TableData table)
		{
			this.gameTableCardsCache.AddRange(table.GameTableCardsList);
			//this.gameTableCardsCache.Update();
			this.userBetRecordCache.AddRange(table.UserBetRecordList);
			//this.userBetRecordCache.Update();
			this.userHandCardsCache.AddRange(table.UserHandCardsList);
			//this.userHandCardsCache.Update();
			this.userAndTableCache.AddRange(table.UserAndTableList);
			//this.userAndTableCache.Update();
			this.userHandScoreCache.AddRange(table.UserInTableHandScoreList);
			//this.userHandScoreCache.Update();
			//this.userSaveTableRecordCache.AddRange(table.UserSaveTableList);
			//this.userSaveTableRecordCache.Update();
		}

		/// <summary>
		/// 清除桌子对象
		/// </summary>
		/// <param name="table"></param>
		/// <param name="roomId"></param>
		public void DeleteTable(TableData table, int roomId = 1001)
		{
			//删除所有的邀请信息
			ClearInviteRecordByTableId(table.TableId);
			Tool.WriteErrorLine("同步所有的牌桌数据");

			RoomData roomData = GetRoomData(roomId);
			if (roomData.Tables.Remove(table.TableId))
			{
				Tool.WriteLine(string.Format("桌子:{0} 移除成功", table.TableId));
				table.ClearTable();
			}
			else
			{
				Tool.WriteErrorLine(string.Format("桌子:{0} 移除失败", table.TableId));
			}
		}

		/// <summary>
		/// 同步玩家的统计数据
		/// </summary>
		private void SyncUsersPlayingData(TableData table)
		{
			foreach (var data in table.UserGameDatas)
			{
				var id = data.Key;
				var value = data.Value;
				var user = GameTable.Current.GetUser(id);
				if (user != null)
				{
					user.ModifyLocked(() =>
					{
						//user.AddChipBeforeShowCardCount += value.AddChipBeforeShowCardCount;
						user.AddChipCount += value.AddChipCount;
						user.EnterTableCount += value.EnterTableCount;
						user.ForgiveByAddChipCount += value.ForgiveByAddChipCount;
						user.ForgiveByThreeBETCount += value.ForgiveByThreeBETCount;
						user.LookAndShowCardsCount += value.LookAndShowCardsCount;
						user.ShowCardsCount += value.ShowCardsCount;
						user.ThreeBETCount += value.ThreeBETCount;
						user.TotalPeriodsCount += value.TotalPeriodsCount;
						user.WinPeriodsCount += value.WinPeriodsCount;
						user.WinTimesByShowCardsCount += value.WinTimesByShowCardsCount;
					});
				}
				else
				{
					Console.WriteLine(string.Format("同步玩家:{0}数据的时候玩家不存在", user.Pid));
				}
			}

		}

		/// <summary>
		/// 游戏结束，更在游戏分成后面
		/// </summary>
		/// <param name="table"></param>
		public void GameOver(TableData table)
		{
			//停止定时器,设置游戏状态
			//table.State = TableState.GameOver;

			//同步玩家的筹码
			this.SyncAllChip(table);

			table.StopTimer();
			var param = new Parameters();
			param["TableId"] = table.TableId;
			SyncNotifyAction((int)ActionType.DZBrocastGameOver, table, param, t =>
			{
				Tool.WriteLine("30017广播游戏结束协议");
			});
			Tool.WriteWarmingLine(string.Format("桌子:{0}游戏结束", table.TableId));

			//清空掉牌局申请记录
			if (this.BeInvitedInfo.ContainsKey(table.TableLogicID))
			{
				this.BeInvitedInfo[table.TableLogicID].Clear();
				this.BeInvitedInfo.Remove(table.TableLogicID);
			}
			table.SyncCurrentHandRecord();  //游戏结束同步玩家的下注记录

			//将当前一局的玩家数据添加到各个玩家的属性上
			this.SyncUsersPlayingData(table);

			table.TableDataReset();
			//检测没有筹码的玩家，强迫弹出
			this.CheckPlayersChip(table);
			//延迟并且设置定时器开始
			System.Threading.Thread.Sleep(800);
			//判断时间是否到，如果到了就不开局，弹出结账单，并且退出玩家清空桌子对象
			if (table.TimeIsOver)
			{
				Tool.WriteErrorLine("TODO:时间到不能进行下一局,强退玩家,释放桌子内存，弹出清单");

				//弹出账单
				#region 下发成绩单
				var realTimeRecordList = new List<RealTimeRecord>();
				foreach (var record in table.GetRealTimeRecordList())
				{
					var realRecord = record.Value;
					var newRecord = new RealTimeRecord();
					newRecord.SUser = realRecord.SUser;
					newRecord.BuyChip = realRecord.BuyChip;
					//判断当前是否在位子上，如果在的话则要加上当前自己位置上的筹码
					int posChip = 0;
					foreach (var posData in table.Positions)
					{
						if (posData.UserId == newRecord.SUser.UserId)
						{
							posChip = posData.Chip;
							break;
						}
					}
					newRecord.WinChip = posChip + realRecord.LeftChip - realRecord.BuyChip;  //当前剩余的筹码-申请的筹码数量
					realTimeRecordList.Add(newRecord);
					//var userAndTableID = this.NewTableId + this.userAndTableNextNo;
					//Tools.Tool.WriteErrorLine(string.Format("玩家游戏牌桌:{0}", userAndTableID));
					//记录到玩家牌桌
					//table.UserAndTables.Add(new UserAndTable() { ID = userAndTableID, UserID = newRecord.SUser.UserId, TableID = table.GTableData.TableID, Profit = newRecord.WinChip, IsMaster = table.TableMaster.UserId == newRecord.SUser.UserId, NickName = newRecord.SUser.NickName, HeadIcon = newRecord.SUser.HeadIcon });
					table.UserAndTableList.Add(new SharedUserAndTable() { TableID = table.TableLogicID, UserID = newRecord.SUser.UserId, Profit = newRecord.WinChip, IsInsurance = false, TotalBuy = newRecord.BuyChip });
				}
				//开通保险才添加保险人
				if (table.Insurance)
				{
					var insurer = GameTable.Current.GetUser(table.InsureId);
					if (insurer != null)
					{
						var insurerRecord = new RealTimeRecord() { BuyChip = 0, SUser = new SimpleUserData() { UserId = insurer.UserId, NickName = insurer.GetNickName(), HeadIcon = insurer.HeadIcon }, WinChip = table.TableInsurer.Chip, IsInsurancer = true };
						realTimeRecordList.Add(insurerRecord);
						table.UserAndTableList.Add(new SharedUserAndTable() { TableID = table.TableLogicID, UserID = insurer.UserId, Profit = table.TableInsurer.Chip, IsInsurance = true });
					}
				}
				var parameters = new Parameters();
				parameters["TableID"] = table.TableId;
				parameters["RealTimeRecords"] = Convert.ToBase64String(ProtoBufUtils.Serialize(realTimeRecordList));
				GameTable.Current.SyncNotifyAction((int)ActionType.DZShowFinalStatement, table, parameters, t =>
				{
					Console.WriteLine("给某个人下发Action 30075 成绩列表");
				});
				#endregion

				//游戏相关数据
				table.GTableData.StopTime = DateTime.Now;
				table.GTableData.TableName = table.TableName;
				table.GTableData.MasterUserId = table.TableMaster.GetUserId();
				table.GTableData.MasterNickName = table.TableMaster.GetNickName();
				table.GTableData.MasterHeadIcon = table.TableMaster.HeadIconBytes;
				table.GTableData.SmallBind = table.BindLevelCost.SmallBind;
				table.GTableData.BigBind = table.BindLevelCost.SmallBind * 2;
				table.GTableData.TableTime = table.TotalTime;
				if (table.Insurance)
					table.GTableData.InsurancerUserID = table.InsureId;
				this.AddGameTableData(table.GTableData);
				//foreach (var userTable in table.UserAndTables)
				//{
				//	this.AddUserAndTable(userTable);
				//}
				//foreach (var record in table.UserBetRecords)
				//{
				//	this.AddGameUserBetRecord(record);
				//}


				//同步所有牌桌记录信息到redis
				this.SyncGameTableData(table);

				//删除牌桌
				//this.DeleteTable(table);
				return;
			}
			else
				this.CheckStart(table);
		}

		/// <summary>
		/// 筹码结算
		/// </summary>
		/// <param name="table"></param>
		/// <param name="chipSetType"></param>
		/// <param name="callBack">结束回调是否开局</param>
		public void ChipSettlement(TableData table, ChipSettlementType chipSetType, Action<TableData> callBack = null)
		{
			switch (chipSetType)
			{
				//其他人都弃牌,所有底池筹码都归该玩家
				case ChipSettlementType.Fold:
					{
						//获得唯一的角色
						var currentPos = table.GetWinner();
						if (currentPos == null)
						{
							Tool.WriteErrorLine("不存在不弃牌的玩家");
							return;
						}
						currentPos.Chip += table.AnteNum;

						var usersWinChip = new List<UsersWinGetChip>();
						var userWinChip = new UsersWinGetChip() { UserId = currentPos.UserId, PosId = currentPos.Id, Chip = table.AnteNum, TotalChip = currentPos.Chip };
						usersWinChip.Add(userWinChip);

						//table.AddCurrentUsersWinChip(new KeyValuePair<int, int>(currentPos.UserId, table.AnteNum));


						foreach (var pos in table.CurrentPlayingPositionData)
						{
							if (pos.UserId == currentPos.UserId)
							{
								table.AddCurrentUserScore(new SharedUserInTableHandScore() { TableID = table.TableLogicID, Hand = table.HandVersionID, Insurance = false, Profit = table.AnteNum - pos.CurrentHandBetChip, UserID = pos.UserId });
							}
							else
							{
								table.AddCurrentUserScore(new SharedUserInTableHandScore() { TableID = table.TableLogicID, Hand = table.HandVersionID, Insurance = false, Profit = -pos.CurrentHandBetChip, UserID = pos.UserId });
							}
						}

						foreach (var score in table.currentUsersScore)
						{
							table.UserInTableHandScoreList.Add(new SharedUserInTableHandScore() { TableID = score.TableID, Hand = score.Hand, Insurance = score.Insurance, Profit = score.Profit, UserID = score.UserID });
						}
						var param = new Parameters();
						param["TableId"] = table.TableId;
						param["UsersWinChip"] = Convert.ToBase64String(ProtoBufUtils.Serialize(usersWinChip));
						table.AnteNum = 0;
						param["AntNum"] = table.AnteNum;  //当前底池的筹码数量

						SyncNotifyAction((int)ActionType.DZBrocastChipSettlement, table, param, t =>
						{
							Tool.WriteLine("30016消息广播玩家获得的筹码");
						});
						//添加胜利统计
						table.AddWinnerCount(currentPos.UserId);
						System.Threading.Thread.Sleep(table.ChipMoveTimeToTablePool);

						GameTable.Current.GameOver(table);
					}
					break;
				case ChipSettlementType.AllIn:
					{
						Tool.WriteErrorLine("AllIn类型没有实现");
					}
					break;
				default:
					Tool.WriteErrorLine("筹码结算类型错误");
					break;
			}
		}

		/// <summary>
		/// 取出桌子底牌并且是否命中保险的判断
		/// </summary>
		/// <returns></returns>
		private List<int> PopBackCards(TableData table)
		{
			var cards = new List<int>();
			Tool.WriteWarmingLine("*************发牌回合:" + table.Round);
			if (table.Round == 1)
			{
				if (table.FirstRoundAllInInInsuranceTable && table.FirstRoundAllInPopCardTimes < 3)
				{
					var card = table.BackCardData[table.FirstRoundAllInPopCardTimes];
					cards.Add(card);
					table.BackUpCardData.Remove(card);
					table.TempBackCardData.Add(card);
					table.FirstRoundAllInPopCardTimes++;
					if (table.FirstRoundAllInPopCardTimes == 3)
					{
						Tool.WriteErrorLine("*****************当期已经是第三回合");
						table.FirstRoundAllInInInsuranceTable = false;
					}

					//命中保险判断，要循环遍历所有的保险底池，结算保险
					Tool.WriteErrorLine("单独发放命中保险判断");
					//支持保险功能，并且当前回合有玩家购买了保险

					if (table.Insurance)
					{
						for (int i = 0; i < table.InsurancePool.Count; i++)
						{
							var pool = table.InsurancePool[i];
							if (!pool.IsBuyInsurance)
							{
								continue;
							}
							//判断是否命中
							bool hitCard = false;
							foreach (var outCard in pool.BuyOuts)
							{
								if (card == outCard) //命中
								{
									hitCard = true;
									break;
								}
							}
							if (hitCard) //命中
							{
								table.InsurancerWin -= pool.CurrentRoundCompensate;
								table.AddInsuranceCompansate(pool.MaxUserId, pool.CurrentRoundCompensate);
							}
							else //没有命中的话 保险人得钱
							{
								table.InsurancerWin += pool.ActualBuyNum;
							}
						}
					}
				}
				else  //三张牌一起发
				{
					for (int i = 0; i < 3; i++)
					{
						cards.Add(table.BackCardData[i]);
						table.BackUpCardData.Remove(table.BackCardData[i]);
						table.TempBackCardData.Add(table.BackCardData[i]);
					}
				}
			}

			//发最后两张牌的回合
			else
			{
				//添加统计
				foreach (var pos in table.CurrentPlayingPositionData)
				{
					if (pos.PlayState != PositionPlayState.Fold)
						table.AddThreeBETCount(pos.UserId);
				}

				var card = table.BackCardData[table.Round + 1];
				cards.Add(card);
				table.BackUpCardData.Remove(card);
				table.TempBackCardData.Add(card);

				for (int i = 0; i < table.InsurancePool.Count; i++)
				{
					var pool = table.InsurancePool[i];
					if (!pool.IsBuyInsurance)
					{
						continue;
					}
					//判断是否命中
					bool hitCard = false;
					foreach (var outCard in pool.BuyOuts)
					{
						if (card == outCard) //命中
						{
							hitCard = true;
							break;
						}
					}
					if (hitCard) //命中
					{
						table.InsurancerWin -= pool.CurrentRoundCompensate;
						table.AddInsuranceCompansate(pool.MaxUserId, pool.CurrentRoundCompensate);
					}
					else //没有命中的话 保险人得钱
					{
						table.InsurancerWin += pool.ActualBuyNum;
					}
				}
			}
			return cards;
		}

		public GameUser GetUser(int userId)
		{
			return _userCacheSet.FindKey(userId.ToString());
		}

		public List<GameUser> GetUserInAreaCode(string areaCode)
		{
			return _userCacheSet.FindGlobal(i => i.CityCode == areaCode);
		}

		/// <summary>
		/// 通知用户数据发生改变
		/// </summary>
		/// <param name="userId"></param>
		public void NotifyUserChange(int userId)
		{
			GameUser user = GetUser(userId);
			if (user != null)
			{
				//TODO:用户信息改变
				//SyncNotifyAction(ActionIDDefine.Cst_Action1014, user, null, null);
			}
		}

		/// <summary>
		/// 给当前房间所有玩家广播消息
		/// </summary>
		/// <param name="actionId"></param>
		/// <param name="table"></param>
		/// <param name="parameters"></param>
		/// <param name="callback"></param>
		public void SyncNotifyAction(int actionId, TableData table, Parameters parameters, Action<int> callback)
		{
			SyncNotifyAction(actionId, ClientNotifier.GetUserList(table), parameters, callback);
		}

		/// <summary>
		/// 给单个玩家广播消息
		/// </summary>
		/// <param name="actionId"></param>
		/// <param name="user"></param>
		/// <param name="parameters"></param>
		/// <param name="callback"></param>
		public void SyncNotifyAction(int actionId, GameUser user, Parameters parameters, Action<int> callback)
		{
			ClientNotifier.NotifyAction(actionId, user, parameters, callback);
		}

		/// <summary>
		/// 异步通知Action处理
		/// </summary>
		/// <param name="actionId"></param>
		/// <param name="userList"></param>
		/// <param name="parameters"></param>
		/// <param name="callback"></param>
		public void SyncNotifyAction(int actionId, List<GameUser> userList, Parameters parameters, Action<int> callback)
		{
			ClientNotifier.NotifyAction(actionId, userList, parameters, callback);
		}

		/// <summary>
		/// 广播出牌
		/// </summary>
		/// <param name="tableData"></param>
		private void BroadCastPopBackCards(TableData tableData, Action<TableData> callBack = null)
		{
			var cards = this.PopBackCards(tableData);
			if (cards != null)
			{
				var cardsparam = new Parameters();
				cardsparam["TableId"] = tableData.TableId;
				cardsparam["BackCards"] = Convert.ToBase64String(ProtoBufUtils.Serialize(cards));

				//广播桌子底牌
				SyncNotifyAction((int)ActionType.DZBrocastBackCards, tableData, cardsparam, t =>
				{
					TraceLog.WriteComplement("消息30005 广播发送桌子底牌 桌子:{0}广播发底牌", tableData.TableId);
				});
			}
			else
			{
				Tool.WriteErrorLine("当前底牌不存在");
				return;
			}
			Tool.WriteErrorLine("*******************广播每个玩家手牌的牌型");
			//判断是否是首次桌子上三张牌一张一张发的时候
			if (tableData.FirstRoundAllInInInsuranceTable)
			{
				//广播每个玩家的牌型
				Tool.WriteErrorLine("广播三张牌一个一个发的时候的牌型");
				BroadcastPlayersCardType(tableData);
			}
			else
			{
				//广播每个玩家当前牌型
				foreach (var playerPos in tableData.CurrentPlayingPositionData)
				{
					if (playerPos.PlayState == PositionPlayState.Fold || playerPos.PlayState == PositionPlayState.None)
						continue;
					var cardData = playerPos.CardData;
					var cardParam = new Parameters();
					cardParam["TableId"] = tableData.TableId;
					cardParam["UserId"] = playerPos.UserId;
					cardParam["PosId"] = playerPos.Id;
					var player = playerPos.CurrentGameUser();

					var lastCardData = new int[this._cardRole.MAX_CENTERCOUNT];
					var cardType = this._cardRole.FiveFromOther(cardData.ToArray(), this._cardRole.MAX_COUNT, tableData.TempBackCardData.ToArray(), tableData.TempBackCardData.Count, ref lastCardData, this._cardRole.MAX_CENTERCOUNT);

					#region 新出一张牌选择最佳五张牌并且判断牌型log
					//Tools.Tool.WriteErrorLine("位置：" + playerPos.Id + "****************输出所有的牌***************");
					//foreach (var card in cardData)
					//{
					//	Tools.Tool.WriteErrorLine(card.ToString());
					//}
					//foreach (var card in tableData.TempBackCardData)
					//{
					//	Tools.Tool.WriteErrorLine(card.ToString());
					//}
					//Tools.Tool.WriteErrorLine("******************最佳牌型********************");
					//foreach (var card in lastCardData)
					//{
					//	Tools.Tool.WriteWarmingLine(card.ToString());
					//}
					//Tools.Tool.WriteWarmingLine(cardType.ToString()); 
					#endregion

					cardParam["CardsType"] = (int)cardType;
					if (player != null)
					{
						SyncNotifyAction((int)ActionType.DZBroadCastPlayerCardType, player, cardParam, t =>
						{
							TraceLog.WriteComplement("广播消息20025 发送每个玩家的手牌类型 桌子:{0} 座位:{1}", tableData.TableId, player.Property.GetPositionId(tableData.TableId));
						});
					}
					else
					{
						Console.WriteLine("广播消息20025没有找到id为:{0}的玩家", player.GetUserId());
					}
				}
			}
			//清空保险相关的记录
			//if (tableData.Insurance)
			//	tableData.InsuranceModelData.RoundClear();
			if (callBack != null)
			{
				callBack(tableData);
				callBack = null;
			}
		}

		/// <summary>
		/// 同步玩家和桌底筹码
		/// </summary>
		/// <param name="tableData"></param>
		public void SyncAllChip(TableData tableData)
		{
			var userChips = new List<UserBeat>();
			var allUsersPos = tableData.GetCurrentGetReadyPosition();
			foreach (var pos in allUsersPos)
			{
				userChips.Add(new UserBeat() { UserId = pos.UserId, PosId = pos.Id, Chip = pos.Chip });
			}
			var param = new Parameters();
			param["TableId"] = tableData.TableId;
			param["TableAnt"] = tableData.AnteNum;
			param["UsersChip"] = Convert.ToBase64String(ProtoBufUtils.Serialize(userChips));

			//广播同步所有玩家的筹码
			SyncNotifyAction((int)ActionType.DZSyncAllChipNum, tableData, param, t =>
			{
				TraceLog.WriteComplement("消息30009 广播同步所有玩家的筹码和底池筹码 桌子:{0}广播发底牌", tableData.TableId);
			});
			System.Threading.Thread.Sleep(1000);
		}
		public void RoundOperate(ChipSettlementType type, TableData tableData)
		{
			if (tableData.Round >= 4)
			{
				Tool.WriteErrorLine("RoundOperate回合操作>4 游戏结束");
				this.CollectChip(tableData);
				this.OnEventGameConclude(tableData);
				return;
			}
			switch (type)
			{
				case ChipSettlementType.Fold:
					{
						//直接进入分成
						this.ChipSettlement(tableData, ChipSettlementType.Fold, this.CheckStart);
					}
					break;
				case ChipSettlementType.AllIn:
					{
						//判断是否有保险功能，如果有要判断是否保存记录，要看是否命中，如果没有的话就直接
						BroadCastPopBackCards(tableData, NextBet);
					}
					break;
				case ChipSettlementType.None: //正常下注的情况
					{
						Tool.WriteErrorLine("回合结束操作 ChipSettlementType.None");
						BroadCastPopBackCards(tableData, (newTable) =>
						{
							//轮到当前玩家下注,要指定最小注码
							var posId = newTable.FormalNormalOperatePosID;
							var position = newTable.Positions[posId - 1];
							var ChipParam = new Parameters();
							ChipParam["TableID"] = newTable.TableId;
							ChipParam["UserID"] = position.UserId;
							ChipParam["PosID"] = posId;
							ChipParam["BetType"] = (int)BetType.Look;  //看牌的状态
							int minChip = 0;
							if (!newTable.IsGripper)
								minChip = newTable.BindLevelCost.SmallBind * 4;//参考大头德扑,下一轮下注最小是大盲的数量
							else
								minChip = newTable.BindLevelCost.SmallBind * 2;//参考大头德扑,下一轮下注最小是大盲的数量
							ChipParam["MinChip"] = minChip;
							ChipParam["Time"] = newTable.OperationSecTimeout;  //下注响应时间
							tableData.CurrentBetPos = position;
							position.BetState = true;
							SyncNotifyAction((int)ActionType.DZBrocastPlayBeginBet, newTable, ChipParam, t =>
							{
								TraceLog.WriteComplement("广播30006 通知某个玩家开始操作 桌子:{0} 座位:{1}开始选择下注", newTable.TableId, posId);
							});

							//启动定时器，开始轮流下注
							newTable.ReStartTimer(newTable.OperationSecTimeout + newTable.OperationSecTimeoutOffset);
						});
					}
					break;
			}
		}

		/// <summary>
		/// 检测是否游戏结束,剩下一个人或者所有人都AllIn
		/// </summary>
		/// <param name="tableData"></param>
		/// <returns></returns>
		public ChipSettlementType CheckGameState(TableData tableData)
		{
			if (tableData.OtherPlayersAreAllFoldExceptOne())
				return ChipSettlementType.Fold;
			if (tableData.PlayersAreAllInExceptFold())
				return ChipSettlementType.AllIn;
			return ChipSettlementType.None;
		}

		private void ClearInsurance(TableData tableData)
		{
			//Tool.WriteErrorLine("删除信息");
			//tableData.winnerListIndex = 0;
			tableData.TempUserCardsDic.Clear();
			tableData.TempWinnerList.Clear();
			tableData.InsuranceCallBack = null;
		}

		/// <summary>
		/// 保险逻辑  依次等待所有的玩家操作完保险
		/// </summary>
		/// <param name="tableData"></param>
		public void RoundInsuranceOperate(TableData tableData)
		{
			System.Threading.Thread.Sleep(500);
			//如果所有的玩家都参与了保险 则直接进入回合结束逻辑
			bool insuranceAreAllOperated = true;
			foreach (var r in tableData.CurrentRoundBuyInsuranceUsersID)
			{
				if (!r.Value)
				{
					insuranceAreAllOperated = false;
					break;
				}
			}
			if (insuranceAreAllOperated)
			{
				if (tableData.State == TableState.Insurance)
					tableData.StopTimer();
				AllInStateNextRound(tableData);
			}
			else
			{
				Tool.WriteLine("继续等待玩家操作");
				//继续等待

			}
		}

		//AllIn状态下的下一个回合
		private void AllInStateNextRound(TableData tableData)
		{
			tableData.RoundReset();
			this.RoundOperate(ChipSettlementType.AllIn, tableData);
		}

		public void RoundInsurance(TableData tableData) //玩家的手牌
		{
			System.Threading.Thread.Sleep(500);
			//所有的要参与的人都已经操作了保险 则结束操作  
			if (tableData.InsurancePool.Count <= 0)
			{
				this.AllInStateNextRound(tableData);
				return;
			}
			else
			{
				var tempInsurancePool = new List<SimpleInsuranceModelPool>();
				OutsOddsInfo odds = null;
				for (int i = 0; i < tableData.InsurancePool.Count; i++)
				{
					var pool = tableData.InsurancePool[i];
					if (pool.IsCanShowInsurance && !pool.CurrentRoundIsOperated)
						tempInsurancePool.Add(pool);
				}
				if (tempInsurancePool.Count <= 0)
				{
					this.AllInStateNextRound(tableData);
					return;
				}
				else //触发保险
				{
					var showInsurance = false;
					var outsList = new ShareCacheStruct<OutsOddsInfo>().FindAll();

					//已经发了三张桌子牌了
					showInsurance = false;
					for (int j = 0; j < tempInsurancePool.Count; j++)
					{
						var pool = tempInsurancePool[j];
						List<int> newouts = null;
						//大于第一回合
						if (tableData.Round > 1)
							newouts = this._cardRole.GetInsuranceCardsMoreThanFive(pool.MaxCardsPosId, tableData.TempUserCardsDic, tableData.TempBackCardData, tableData.BackUpCardData);
						else  //第一回合 发三张底牌的时候
							newouts = this._cardRole.GetInsuranceCardsLessThanFive(pool.MaxCardsPosId, tableData.TempUserCardsDic, tableData.TempBackCardData, tableData.BackUpCardData);
						if (newouts == null)
							continue;
						else if (newouts.Count <= 0)
							continue;
						else
						{
							Tool.WriteErrorLine("打印outs牌数量:" + newouts.Count);
							foreach (var o in newouts)
							{
								Tool.WriteErrorLine(o.ToString());
							}
							if (newouts.Count > 8)
							{
								var dic = tableData.TempUserCardsDic;
							}
							showInsurance = true;
							pool.Outs.AddRange(newouts);
							var comm = new List<int>();
							comm.AddRange(tableData.TempBackCardData);
							//for (int i = comm.Count; i < 4; i++)
							//{
							//	comm.Add(-1);
							//}
							pool.Common = comm;

							var num = pool.Outs.Count;
							if (num > outsList.LastOrDefault().Outs)
							{
								odds = outsList.Max();
							}
							else
							{
								odds = outsList.Where(i => i.Outs == num).First();
							}
							if (odds == null)
							{
								Tool.WriteErrorLine("没有找到对应的赔率");
								this.AllInStateNextRound(tableData);
								return;
							}
							pool.Odds = odds.Odds;
							pool.MaxCanBuyChip = tableData.MaxCanBuyChipNum(pool.AntNum, pool.MaxUserId);
						}
					}
					//如果没有一个保险弹框可以弹出 则直接退出
					if (!showInsurance)
					{
						this.AllInStateNextRound(tableData);
						return;
					}

					//给相关的人发送相关的List<Pool>的字符串
					var poolDic = new Dictionary<int, List<SimpleInsuranceModelPool>>();
					foreach (var p in tempInsurancePool)
					{
						if (poolDic.ContainsKey(p.MaxUserId))
						{
							poolDic[p.MaxUserId].Add(p);
						}
						else
						{
							var list = new List<SimpleInsuranceModelPool>();
							list.Add(p);
							poolDic.Add(p.MaxUserId, list);
						}
					}
					tableData.CurrentRoundBuyInsuranceUsersID.Clear();
					foreach (var p in poolDic)
					{
						var user = GameTable.Current.GetUser(p.Key);
						if (user != null)
						{
							var poolsList = p.Value;
							if (poolsList.Count <= 0)
							{
								Tool.WriteErrorLine("不存在该玩家的底池数据");
								continue;
							}
							var insuranceModelStr = Convert.ToBase64String(ProtoBufUtils.Serialize(p.Value));
							var param = new Parameters();
							param["TableId"] = tableData.TableId;
							param["Time"] = tableData.InsuranceOperationTime;
							param["InsuranceModel"] = insuranceModelStr;
							Tool.WriteErrorLine("发送保险消息");
							//给相关的人发送消息
							SyncNotifyAction((int)ActionType.DZShowInsurancePanle, user, param, t =>
							{
								Console.WriteLine(string.Format("30025 显示保险弹框"));
							});

							tableData.CurrentRoundBuyInsuranceUsersID.Add(user.UserId, false);
						}
					}

					//没有可以操作保险的保险人 则继续下一轮
					if (tableData.CurrentRoundBuyInsuranceUsersID.Count == 0)
					{
						this.AllInStateNextRound(tableData);
						return;
					}
					else
					{
						tableData.State = TableState.Insurance;
						//开启定时器
						tableData.ReStartTimer(tableData.InsuranceOperationTime);
					}
				}
			}
		}

		private void FirstRoundAllIn(TableData tableData)
		{
			//先清空保险底池
			tableData.InsurancePool.Clear();

			GameEnd gameEnd = new GameEnd();
			gameEnd.TotalEnd = 1;

			Dictionary<int, DeckType> cardsType;
			//获得新的五张手牌数据
			var userCardsDic = _cardRole.CombineMinFiveCards(tableData.TempUserCardsDic, tableData.TempBackCardData, tableData.BackUpCardData, out cardsType);

			var newPlayerCount = tableData.CurrentPlayingPositionData.Count;

			var newCurrentAllInPositions = new List<PositionData>();
			for (int i = 0; i < newPlayerCount; i++)
			{
				var posData = tableData.CurrentPlayingPositionData[i];
				//排除弃牌玩家
				if (posData.PlayState == PositionPlayState.Fold)
					continue;
				posData.CurrentHandTempBetChip = posData.CurrentHandBetChip;
				newCurrentAllInPositions.Add(posData);
			}

			var newLastCenterCardData = new List<int[]>();

			foreach (var pair in userCardsDic)
			{
				int[] cards = pair.Value.ToArray();
				newLastCenterCardData.Add(cards);
			}

			//总下注备份
			List<int> newTotalScore = new List<int>();
			newTotalScore.AddRange(tableData.TotalScore);


			//临时保存的最后没有弃牌玩家的最大牌数组
			var newTempCardDataList = new List<int[]>();
			newTempCardDataList.AddRange(newLastCenterCardData);

			int newWinCount = 0;
			try
			{
				//用户得分顺序
				for (int i = 0; i < newPlayerCount; i++)
				{
					UserWinList winner = new UserWinList();
					tableData.TempWinnerList.Add(winner);
					//查找最大用户,如果没有的话就进入内部直接这个玩家
					if (!this._cardRole.SelectMaxUser(newTempCardDataList, ref winner, ref newTotalScore))
					{
						newWinCount = i;
						break;
					}

					//删除胜利数据
					for (int j = 0; j < tableData.TempWinnerList[i].SameCount; j++)
					{
						var removeIndex = tableData.TempWinnerList[i].WinerList[j];
						if (newTempCardDataList[removeIndex][0] == 0)
						{
							Tool.WriteErrorLine("不应该为0");
							return;
						}
						//清空数组
						Array.Clear(newTempCardDataList[removeIndex], 0, newTempCardDataList[removeIndex].Length);
					}
				}
			}
			catch (Exception ex)
			{
				Tool.WriteErrorLine("选择最大用户错误");
				Tool.WriteErrorLine(ex.ToString());
			}

			try
			{
				//根据当前一手牌下注的筹码升序排列
				#region 计算保险底池(区分主边池)
				newCurrentAllInPositions.Sort((x, y) => x.CurrentHandBetChip.CompareTo(y.CurrentHandBetChip));

				var tempPosList = new List<PositionData>();
				tempPosList.AddRange(newCurrentAllInPositions);

				var tPosList = new List<PositionData>();
				bool mainPool = true;
				int number = 0;
				for (int j = 0; j < tempPosList.Count; j++)
				{
					tPosList.Clear();
					var p = new SimpleInsuranceModelPool();
					int tempMin = 0;
					for (int i = 0; i < tempPosList.Count; i++)
					{
						if (tempPosList[i].CurrentHandTempBetChip > 0)
						{
							tempMin = tempPosList[i].CurrentHandTempBetChip;
							break;
						}
					}

					//当前底池的参考玩家列表
					for (int i = 0; i < tempPosList.Count; i++)
					{
						if (tempPosList[i].CurrentHandTempBetChip > 0)
						{
							tempPosList[i].CurrentHandTempBetChip -= tempMin;
							if (tempPosList[i].CurrentHandTempBetChip >= 0)
								tPosList.Add(tempPosList[i]);
						}
					}

					//要根据牌型大小排序
					if (tPosList.Count > 0)
					{
						foreach (var pos in tPosList)
						{
							p.ListUsr.Add(new UserAndOuts() { UserID = pos.UserId, Cards = pos.CardData, OustsCount = 0 });
						}
						p.IsMainPool = mainPool;
						p.NumberID = number++;
						p.AntNum = tempMin * p.ListUsr.Count;
						p.PerBetNum = tempMin;
						p.TableID = tableData.TableId;

						//判断TempWinnerList 中唯一最大值是不是在当前这个列表里面
						if (tPosList.Count > 1)
						{
							var containsMax = false;
							//按照牌型大小顺序在当前保险池里面找相同的位置的计数，如果找到一样的+1;
							int searchCount = 0;

							var maxUserId = 0;
							var maxPosId = -1;
							for (int i = 0; i < tableData.TempWinnerList.Count; i++)
							{
								var winner = tableData.TempWinnerList[i];
								searchCount = 0;

								foreach (var tPos in tPosList)
								{
									if (tableData.CurrentPlayingPositionData[winner.WinerList[0]].Id == tPos.Id)
									{
										maxUserId = tPos.UserId;
										maxPosId = tPos.Id;
										if (winner.SameCount == 1)
										{
											containsMax = true;
											break;
										}
										else
										{
											++searchCount;
											if (searchCount >= 2)
											{
												break;
											}
										}
									}
								}
								if (containsMax || searchCount == 1)
								{
									p.IsCanShowInsurance = true;
									p.MaxUserId = maxUserId;
									p.MaxCardsPosId = maxPosId;
									break;
								}
							}
						}
					}
					if (p.PerBetNum != 0)
					{
						tableData.AddInsuranceModel(p);
						mainPool = false;
					}
				}
				#endregion

			}
			catch (Exception ex)
			{
				Tool.WriteErrorLine("保险判断有误" + ex.ToString());
			}

			this.RoundInsurance(tableData);
		}

		public void NextBet(TableData tableData)
		{
			//游戏结束
			if (tableData.Round >= 4 || tableData.CurrentPlayingPositionData.Count < 2)
			{
				Tool.WriteErrorLine("游戏结束筹码添加进底池");
				//将筹码加入底池
				this.CollectChip(tableData);
				System.Threading.Thread.Sleep(tableData.ChipMoveTimeToTablePool);
				this.OnEventGameConclude(tableData);
				return;
			}

			//不是AllIn翻牌阶段
			if (!tableData.AllInState)
			{
				//广播下一个玩家下注
				var nextPos = tableData.GetNextPosition();
				//如果不存在则说明已经是一个下注回合结束，如果其他人都弃牌或者AllIn 就要考虑直接发牌比大小
				if (nextPos != null)
				{
					Tool.WriteErrorLine("当前回合是**" + tableData.Round);
					if (tableData.PlayersAreAllInExceptFold())
					{
						tableData.AllInState = true;
					}

					//广播给其他玩家轮到某玩家开始下注
					var betParam = new Parameters();
					betParam["TableId"] = tableData.TableId;
					betParam["UserID"] = nextPos.UserId;
					betParam["PosId"] = nextPos.Id;

					//给当前玩家广播下注消息
					var currentUser = nextPos.CurrentGameUser();
					if (currentUser == null)
					{
						Tool.WriteWarmingLine("当前位置没有人");
						return;
					}

					var betType = BetType.Follow;
					if (tableData.CurrentMaxChip == 0)
					{
						betType = BetType.Look;
					}
					else if (tableData.CurrentMaxChip >= nextPos.Chip)
					{
						betType = BetType.AllIn;
					}
					betParam["BetType"] = (int)betType;
					var minChip = tableData.CurrentMaxChip - nextPos.CurrentRoundChip;
					betParam["MinChip"] = minChip;
					betParam["Time"] = tableData.OperationSecTimeout;
					tableData.CurrentBetPos = nextPos;
					nextPos.BetState = true;
					SyncNotifyAction((int)ActionType.DZBrocastPlayBeginBet, tableData, betParam, t =>
					{
						TraceLog.WriteComplement("广播消息30006 轮到桌子:{0} 座位:{1}开始下注", tableData.TableId, nextPos.Id);
					});
					//玩家下注 开启定时器
					tableData.ReStartTimer(tableData.OperationSecTimeout + tableData.OperationSecTimeoutOffset);
					return;
				}
				//一个回合结束
				else
				{
					Tool.WriteErrorLine("当前回合结束，没有找到要下注的玩家");
				}
			}
			//翻牌比牌结算
			else
			{
				Tool.WriteLine("AllIn阶段");
			}


			//回合结束清空临时玩家手牌
			tableData.TempUserCardsDic.Clear();
			//广播每个玩家当前牌型
			foreach (var playerPos in tableData.CurrentPlayingPositionData)
			{
				if (playerPos.PlayState == PositionPlayState.Fold || playerPos.PlayState == PositionPlayState.None)
					continue;
				tableData.TempUserCardsDic.Add(playerPos.Id, playerPos.CardData);
			}

			bool firstRoundAllIn = false;
			//第一回合大家还没有全allin
			if (!tableData.FirstRoundAllInInInsuranceTable)
			{
				//筹码加入底池
				CollectChip(tableData);

				Tool.WriteErrorLine(tableData.Round + "回合结束,回合数据重置");
				tableData.RoundReset();

				System.Threading.Thread.Sleep(tableData.ChipMoveTimeToTablePool);

				//判断大家是否AllIn
				if (tableData.PlayersAreAllInExceptFold())
				{
					tableData.AllInState = true;
					if (tableData.Round == 0 && tableData.Insurance)
						tableData.FirstRoundAllInInInsuranceTable = true;    //第一回合就AllIn
				}

				//游戏盘数记录
				tableData.Round++;
				Tool.WriteErrorLine(string.Format("新的回合{0}开始", tableData.Round));

				//bool nextRound = false;
				bool roundInsuranceGoToNext = false;

				//触发保险
				if (tableData.Insurance)
				{
					//开始准备发三张桌子牌
					if (tableData.Round == 1 && tableData.FirstRoundAllInInInsuranceTable)
					{
						firstRoundAllIn = true;
						FirstRoundAllIn(tableData);
						return;
					}
					else if (tableData.Round > 1 && tableData.Round < 4)
					{
						//每一个回合触发保险流程
						if (tableData.AllInState)
						{
							Tool.WriteErrorLine("进入保险逻辑");

							//先清空保险底池
							tableData.InsurancePool.Clear();

							var playerCount = tableData.CurrentPlayingPositionData.Count;
							var lastCenterCardData = new List<int[]>();  //每一个玩家的最大手牌牌型
							var currentAllInPositions = new List<PositionData>();
							for (int i = 0; i < playerCount; i++)
							{
								var posData = tableData.CurrentPlayingPositionData[i];
								//排除弃牌玩家
								if (posData.PlayState == PositionPlayState.Fold)
									continue;
								posData.CurrentHandTempBetChip = posData.CurrentHandBetChip;
								currentAllInPositions.Add(posData);
								var lastCardData = new int[this._cardRole.MAX_CENTERCOUNT];
								//最大牌型
								var endCardType = this._cardRole.FiveFromOther(posData.CardData.ToArray(), this._cardRole.MAX_COUNT, tableData.TempBackCardData.ToArray(), tableData.TempBackCardData.Count, ref lastCardData, this._cardRole.MAX_CENTERCOUNT);
								lastCenterCardData.Add(lastCardData);
							}

							//总下注备份
							List<int> totalScore = new List<int>();
							totalScore.AddRange(tableData.TotalScore);

							//临时保存的最后没有弃牌玩家的最大牌数组
							var tempCardDataList = new List<int[]>();
							tempCardDataList.AddRange(lastCenterCardData);

							int winCount = 0;
							try
							{
								tableData.TempWinnerList.Clear();
								tableData.InsuranceCallBack = null;
								//用户得分顺序
								for (int i = 0; i < playerCount; i++)
								{
									UserWinList winner = new UserWinList();
									tableData.TempWinnerList.Add(winner);
									//查找最大用户,如果没有的话就进入内部直接这个玩家
									if (!this._cardRole.SelectMaxUser(tempCardDataList, ref winner, ref totalScore))
									{
										winCount = i;
										break;
									}

									//删除胜利数据
									for (int j = 0; j < tableData.TempWinnerList[i].SameCount; j++)
									{
										var removeIndex = tableData.TempWinnerList[i].WinerList[j];
										if (tempCardDataList[removeIndex][0] == 0)
										{
											Tool.WriteErrorLine("删除胜利数据不应该为0");
											return;
										}
										//清空数组
										Array.Clear(tempCardDataList[removeIndex], 0, tempCardDataList[removeIndex].Length);
									}
								}
							}
							catch (Exception ex)
							{
								Tool.WriteErrorLine("选择最大用户错误");
								Tool.WriteErrorLine(ex.ToString());
							}

							try
							{
								//根据当前一手牌下注的筹码升序排列
								#region 计算保险底池(区分主边池)
								currentAllInPositions.Sort((x, y) => x.CurrentHandBetChip.CompareTo(y.CurrentHandBetChip));

								var tempPosList = new List<PositionData>();
								tempPosList.AddRange(currentAllInPositions);

								var tPosList = new List<PositionData>();
								bool mainPool = true;
								int number = 0;
								for (int j = 0; j < tempPosList.Count; j++)
								{
									tPosList.Clear();
									var p = new SimpleInsuranceModelPool();
									int tempMin = 0;
									for (int i = 0; i < tempPosList.Count; i++)
									{
										if (tempPosList[i].CurrentHandTempBetChip > 0)
										{
											tempMin = tempPosList[i].CurrentHandTempBetChip;
											break;
										}
									}

									//当前底池的参考玩家列表
									for (int i = 0; i < tempPosList.Count; i++)
									{
										if (tempPosList[i].CurrentHandTempBetChip > 0)
										{
											tempPosList[i].CurrentHandTempBetChip -= tempMin;
											if (tempPosList[i].CurrentHandTempBetChip >= 0)
												tPosList.Add(tempPosList[i]);
										}
									}

									//要根据牌型大小排序
									if (tPosList.Count > 0)
									{
										foreach (var pos in tPosList)
										{
											p.ListUsr.Add(new UserAndOuts() { UserID = pos.UserId, Cards = pos.CardData, OustsCount = 0 });
										}
										p.IsMainPool = mainPool;
										p.NumberID = number++;
										p.AntNum = tempMin * p.ListUsr.Count;
										p.PerBetNum = tempMin;
										p.TableID = tableData.TableId;

										//判断TempWinnerList 中唯一最大值是不是在当前这个列表里面
										if (tPosList.Count > 1)
										{
											var containsMax = false;
											//按照牌型大小顺序在当前保险池里面找相同的位置的计数，如果找到一样的+1;
											int searchCount = 0;

											var maxUserId = 0;
											var maxPosId = -1;
											for (int i = 0; i < tableData.TempWinnerList.Count; i++)
											{
												var winner = tableData.TempWinnerList[i];
												searchCount = 0;

												foreach (var tPos in tPosList)
												{
													if (tableData.CurrentPlayingPositionData[winner.WinerList[0]].Id == tPos.Id)
													{
														maxUserId = tPos.UserId;
														maxPosId = tPos.Id;
														if (winner.SameCount == 1)
														{
															containsMax = true;
															break;
														}
														else
														{
															++searchCount;
															if (searchCount >= 2)
															{
																break;
															}
														}
													}
												}
												if (containsMax || searchCount == 1)
												{
													p.IsCanShowInsurance = true;
													p.MaxUserId = maxUserId;
													p.MaxCardsPosId = maxPosId;
													break;
												}
											}
										}
									}
									if (p.PerBetNum != 0)
									{
										tableData.AddInsuranceModel(p);
										mainPool = false;
									}
								}
								#endregion

								//发送保险弹框
								roundInsuranceGoToNext = true;
								this.RoundInsurance(tableData);
								return;
							}
							catch (Exception ex)
							{
								Tool.WriteErrorLine("保险判断有误" + ex.ToString());
							}
						}
					}
				}
				if (!roundInsuranceGoToNext && !tableData.FirstRoundAllInInInsuranceTable && !firstRoundAllIn)
				{
					var type = this.CheckGameState(tableData);
					//重置最大值为0，并且上一个跟注的人开始下注
					Tool.WriteErrorLine("NextBet操作");
					this.RoundOperate(type, tableData);
					return;
				}
			}
			else
			{
				this.FirstRoundAllIn(tableData);
			}
		}

		/// <summary>
		/// 强制某个座位站起
		/// </summary>
		/// <param name="tableData"></param>
		/// <param name="pos"></param>
		public void ForceStandUp(TableData tableData, PositionData pos)
		{
			if (pos.CurrentGameUser() != null)
			{
				var parameters = new Parameters();
				parameters["TableID"] = tableData.TableId;
				parameters["UserID"] = pos.UserId;
				parameters["PosID"] = pos.Id;
				if (!tableData.StandUp(pos, pos.CurrentGameUser()))
					Tool.WriteErrorLine("玩家站起有异常,之前没有保存该玩家的信息");
				SyncNotifyAction((int)ActionType.DZBrocastGameUserLeaveSet, tableData, parameters, t =>
				{
					Tool.WriteLine("强制没有筹码的玩家站起");
				});
			}
		}

		public void LeaveTable(TableData tableData, GameUser currentGameUser, PositionData pos)
		{
			//下发20009站起消息
			var parameters = new Parameters();
			parameters["TableID"] = tableData.TableId;
			parameters["UserID"] = currentGameUser.GetUserId();
			parameters["PosID"] = pos.Id;
			GameTable.Current.SyncNotifyAction((int)ActionType.DZGameUserStandUp, currentGameUser, parameters, t =>
			{
				Console.WriteLine("下发20009某人离开座位的消息");
			});
		}

		/// <summary>
		/// 检测当前坐下的玩家身上的筹码是否足够，如果不够的话就警告不够并且是否添加筹码弹框，如果确认还要经过管理员同意才能继续，否则被强制站起
		/// </summary>
		/// <param name="tableData"></param>
		private void CheckPlayersChip(TableData tableData)
		{
			Tool.WriteWarmingLine("检测谁没有筹码则被踢出");
			foreach (var pos in tableData.Positions)
			{
				var currentGameUser = pos.CurrentGameUser();
				if (currentGameUser != null)
				{
					if (pos.Chip <= 0)
					{
						var tempPos = pos;
						var tempUser = currentGameUser;
						new Thread(() =>
						{
							Thread.Sleep(tableData.ForceLeaveFromTableTimeout);
							if (tempUser.UserId == tempPos.UserId)
							{
								if (tempPos.Chip <= 0)
								{
									Tool.WriteErrorLine("当前玩家还没有申请筹码，强制退出");
									LeaveTable(tableData, tempUser, tempPos);
								}
								else
								{
									Tool.WriteWarmingLine("当前玩家已经申请了筹码了");
								}
							}
							else
							{
								Tool.WriteWarmingLine("不是之前的那个玩家");
							}
						}).Start();
					}
				}
			}
		}

		//private void ForceLeaveFromTable(object source, System.Timers.ElapsedEventArgs e, TableData tableData, GameUser currentGameUser, PositionData pos)
		//{
		//	Tool.WriteWarmingLine("下发某人被迫站起消息");	
		//	LeaveTable(tableData, currentGameUser, pos);
		//}

		/// <summary>
		/// 广播每个玩家手牌的牌型
		/// </summary>
		/// <param name="tableData"></param>
		private void BroadcastPlayersCardType(TableData tableData)
		{
			var UserCardsDic = new Dictionary<int, List<int>>();
			//广播每个玩家当前牌型
			foreach (var playerPos in tableData.CurrentPlayingPositionData)
			{
				if (playerPos.PlayState == PositionPlayState.Fold || playerPos.PlayState == PositionPlayState.None)
					continue;
				UserCardsDic.Add(playerPos.Id, playerPos.CardData);
			}
			Dictionary<int, DeckType> cardsType;
			//获得新的五张手牌数据
			var userCardsDic = _cardRole.CombineMinFiveCards(UserCardsDic, tableData.TempBackCardData, tableData.BackUpCardData, out cardsType);

			foreach (var pair in userCardsDic)
			{
				var playerPos = tableData.Positions[pair.Key - 1];
				var cardParam = new Parameters();
				cardParam["TableId"] = tableData.TableId;
				cardParam["UserId"] = playerPos.UserId;
				cardParam["PosId"] = playerPos.Id;
				var player = playerPos.CurrentGameUser();

				cardParam["CardsType"] = (int)cardsType[pair.Key];
				if (player != null)
				{
					SyncNotifyAction((int)ActionType.DZBroadCastPlayerCardType, player, cardParam, t =>
					{
						TraceLog.WriteComplement("广播消息20025 发送每个玩家的手牌类型 桌子:{0} 座位:{1}", tableData.TableId, player.Property.GetPositionId(tableData.TableId));
					});
				}
				else
				{
					Console.WriteLine("广播消息20025没有找到id为:{0}的玩家", player.GetUserId());
				}
			}
		}

		/// <summary>
		/// 3S倒计时之后游戏开始
		/// </summary>
		/// <param name="tableData"></param>
		private void StartGame(TableData tableData)
		{
			Tool.WriteWarmingLine("游戏开始");
			if (tableData.TableLogicID == 0)
			{
				tableData.GTableData.TableID = this.GetGameTableDataNextNo();   //游戏开始的时候设置TableID
				tableData.TableLogicID = tableData.GTableData.TableID;
			}
			tableData.TableGameStart();
			var readyPosition = tableData.GetCurrentGetReadyPosition();

			//开始游戏并且要发底牌
			TraceLog.WriteComplement("房间:{0},桌:{1}开始发牌...", tableData.RoomId, tableData.TableId);
			Tool.WriteLine(string.Format("房间:{0} 桌子:{1}开始开局", tableData.RoomId, tableData.TableId));
			foreach (var p in readyPosition)
			{
				p.ReSendCard();
				//将准备好的位置添加进正在玩的缓存座位列表中
				tableData.InsertPlayingPosition(p);
			}
			//初始化游戏中玩家的一些记录数据
			tableData.InitUserGameData();
			//按照座位ID从小到大排序
			tableData.SortPositionData(ref tableData.CurrentPlayingPositionData);

			var bankerPos = tableData.GetBanker();
			if (bankerPos == null)
			{
				Tool.WriteErrorLine("获得庄家失败");
				return;
			}

			//所有玩家增加一次游戏记录
			tableData.AddTotalGameCount();

			//发牌，连同底牌也一起发了
			this.SendCard(tableData, TableData.CardBackNum);

			int chipTemp;
			var param = new Parameters();
			param["TableId"] = tableData.TableId;
			//庄家
			param["BankerId"] = bankerPos.UserId;
			param["BankerPosId"] = bankerPos.Id;

			//小盲
			var chip = tableData.BindLevelCost.SmallBind;
			var nextPos = tableData.GetNextPosition();
			param["SmallBindPosId"] = nextPos.Id;
			if (nextPos.Chip > chip)
			{
				nextPos.CurrentRoundChip += chip;
				nextPos.CurrentHandBetChip += chip;
				nextPos.Chip -= chip;
				tableData.SetBetRecord(tableData.Round, nextPos.Id, chip);
				chipTemp = chip;
				nextPos.PlayState = PositionPlayState.SmallBind;
				//添加当前下注记录
				//tableData.AddUserBetRecordInCurrent(new NewUserBetRecord() { TableID = tableData.TableLogicID, UserID = nextPos.UserId, UserName = nextPos.NickName, UserHeadIcon = nextPos.HeadIcon, Round = tableData.Round, BetType = ((int)nextPos.PlayState).ToEnumDescriptionString(typeof(PositionPlayState)), BetNum = chipTemp });
				//tableData.AddUserBetRecordLog(new LogUserBetRecord() { TableID = tableData.TableId, UserID = nextPos.UserId, UserName = nextPos.NickName, UserHeadIcon = nextPos.HeadIcon, Round = tableData.Round, BetType = ((int)nextPos.PlayState).ToEnumDescriptionString(typeof(PositionPlayState)), BetNum = chipTemp });
				tableData.AddUserBetRecordInCurrent(new SharedUserBetRecord() { TableID = tableData.TableLogicID, UserID = nextPos.UserId, Round = tableData.Round, Hand = tableData.HandVersionID, BetType = ((int)nextPos.PlayState).ToEnumDescriptionString(typeof(PositionPlayState)), BetNum = chipTemp });
			}
			else
			{
				nextPos.CurrentRoundChip += nextPos.Chip;
				nextPos.CurrentHandBetChip += nextPos.Chip;
				tableData.SetBetRecord(tableData.Round, nextPos.Id, nextPos.Chip);
				nextPos.PlayState = PositionPlayState.AllIn;
				nextPos.Chip = 0;

				chipTemp = nextPos.Chip;

				this.OnUserBet(tableData, tableData.TableId, chipTemp, nextPos);
			}

			param["SmallBindBet"] = nextPos.CurrentRoundChip;
			param["SmallBindLeftChip"] = nextPos.Chip;
			//设置当前小盲位最高下注记录
			tableData.SetCurrentMaxChip(chipTemp);
			tableData.SetCurrentMaxChipPosId(nextPos.Id);


			//大盲的筹码
			chipTemp = tableData.BindLevelCost.SmallBind * 2;
			nextPos = tableData.GetNextPosition();
			param["BigBindPosId"] = nextPos.Id;
			//如果筹码足够
			if (nextPos.Chip > chipTemp)
			{
				nextPos.CurrentRoundChip += chipTemp;
				nextPos.CurrentHandBetChip += chipTemp;
				nextPos.Chip -= chipTemp;
				tableData.SetBetRecord(tableData.Round, nextPos.Id, chipTemp);
				//设置最大下注的位置和数量
				tableData.SetCurrentMaxChip(chipTemp);
				tableData.SetCurrentMaxChipPosId(nextPos.Id);
				nextPos.PlayState = PositionPlayState.BigBind;
				//添加当前下注记录
				//tableData.AddUserBetRecordInCurrent(new NewUserBetRecord() { TableID = tableData.TableLogicID, UserID = nextPos.UserId, UserName = nextPos.NickName, UserHeadIcon = nextPos.HeadIcon, Round = tableData.Round, BetType = ((int)nextPos.PlayState).ToEnumDescriptionString(typeof(PositionPlayState)), BetNum = chipTemp });
				//tableData.AddUserBetRecordLog(new LogUserBetRecord() { TableID = tableData.TableId, UserID = nextPos.UserId, UserName = nextPos.NickName, UserHeadIcon = nextPos.HeadIcon, Round = tableData.Round, BetType = ((int)nextPos.PlayState).ToEnumDescriptionString(typeof(PositionPlayState)), BetNum = chipTemp });
				tableData.AddUserBetRecordInCurrent(new SharedUserBetRecord() { TableID = tableData.TableLogicID, UserID = nextPos.UserId, Round = tableData.Round, Hand = tableData.HandVersionID, BetType = ((int)nextPos.PlayState).ToEnumDescriptionString(typeof(PositionPlayState)), BetNum = chipTemp });
			}
			//筹码不够就AllIn
			else
			{
				chipTemp = nextPos.Chip;
				nextPos.CurrentRoundChip += nextPos.Chip;
				nextPos.CurrentHandBetChip += nextPos.Chip;
				tableData.SetBetRecord(tableData.Round, nextPos.Id, nextPos.Chip);
				nextPos.PlayState = PositionPlayState.AllIn;
				nextPos.Chip = 0;

				//如果当前的筹码大于前面的才更改最大下注的记录，否则还是前面的记录
				if (nextPos.Chip > tableData.CurrentMaxChip)
				{
					tableData.SetCurrentMaxChip(nextPos.Chip);
					tableData.SetCurrentMaxChipPosId(nextPos.Id);
				}

				this.OnUserBet(tableData, tableData.TableId, chipTemp, nextPos);
			}
			param["BigBindBet"] = nextPos.CurrentRoundChip;
			param["BigBindLeftChip"] = nextPos.Chip;
			chip = 0;
			chipTemp = 0;
			int gripperPosId = 0;
			//判断是否强制抓头
			//TODO:如果是两个人并且大盲AllIn并且不大于小盲这种情况会有bug,本应该找到小盲的那位，但返回会是null
			if (tableData.IsGripper)
			{
				chip = tableData.BindLevelCost.SmallBind * 4;
				nextPos = tableData.GetNextPosition();
				if (nextPos.Chip > chip)
				{
					nextPos.Chip -= chip;
					nextPos.CurrentRoundChip += chip;
					nextPos.CurrentHandBetChip += chip;
					tableData.SetBetRecord(tableData.Round, nextPos.UserId, chip);
					gripperPosId = nextPos.Id;

					//设置最大下注的位置和数量
					tableData.SetCurrentMaxChip(nextPos.CurrentRoundChip);
					tableData.SetCurrentMaxChipPosId(gripperPosId);

					nextPos.PlayState = PositionPlayState.Muzzle;
					//添加当前下注记录
					//tableData.AddUserBetRecordInCurrent(new NewUserBetRecord() { TableID = tableData.TableLogicID, UserID = nextPos.UserId, UserName = nextPos.NickName, UserHeadIcon = nextPos.HeadIcon, Round = tableData.Round, BetType = ((int)nextPos.PlayState).ToEnumDescriptionString(typeof(PositionPlayState)), BetNum = chip });
					//tableData.AddUserBetRecordLog(new LogUserBetRecord() { TableID = tableData.TableId, UserID = nextPos.UserId, UserName = nextPos.NickName, UserHeadIcon = nextPos.HeadIcon, Round = tableData.Round, BetType = ((int)nextPos.PlayState).ToEnumDescriptionString(typeof(PositionPlayState)), BetNum = chip });
					tableData.AddUserBetRecordInCurrent(new SharedUserBetRecord() { TableID = tableData.TableLogicID, UserID = nextPos.UserId, Round = tableData.Round, Hand = tableData.HandVersionID, BetType = ((int)nextPos.PlayState).ToEnumDescriptionString(typeof(PositionPlayState)), BetNum = chipTemp });
				}
				//筹码不够就AllIn
				else
				{
					chip = nextPos.Chip;
					chipTemp = chip;
					nextPos.CurrentRoundChip += nextPos.Chip;
					nextPos.CurrentHandBetChip += nextPos.Chip;
					tableData.SetBetRecord(tableData.Round, nextPos.UserId, nextPos.Chip);
					nextPos.PlayState = PositionPlayState.AllIn;
					nextPos.Chip = 0;
					gripperPosId = nextPos.Id;

					//如果当前的筹码大于前面的才更改最大下注的记录，否则还是前面的记录
					if (nextPos.Chip > tableData.CurrentMaxChip)
					{
						tableData.SetCurrentMaxChip(nextPos.Chip);
						tableData.SetCurrentMaxChipPosId(gripperPosId);
					}
					this.OnUserBet(tableData, tableData.TableId, chipTemp, nextPos);
				}
			}
			param["GripperPosId"] = gripperPosId;
			param["GripperBet"] = nextPos.CurrentRoundChip;
			param["GripperLeftChip"] = nextPos.Chip;
			SyncNotifyAction((int)ActionType.DZBrocastStartGame, tableData, param, t =>
			{
				TraceLog.WriteComplement("桌子:{0}开局了", tableData.TableId);
				Tool.WriteLine("广播30003开局信息");
				tableData.IsHavaSendCards = true;
			});
			System.Threading.Thread.Sleep(300);
			var positionPlayData = new List<PositionChipData>();
			foreach (var pos in tableData.CurrentPlayingPositionData)
			{
				positionPlayData.Add(new PositionChipData() { PosId = pos.Id, Chip = pos.Chip });
			}
			//广播所有在正在进行游戏的玩家PositionData
			var allUserLeftChipParam = new Parameters();
			allUserLeftChipParam["TableId"] = tableData.TableId;
			allUserLeftChipParam["PositionsChipListString"] = Convert.ToBase64String(ProtoBufUtils.Serialize(positionPlayData));
			SyncNotifyAction((int)ActionType.DZBroadCastAllGameUserChip, tableData, allUserLeftChipParam, t =>
			{
				TraceLog.WriteComplement("桌子:{0} 广播20020桌子中所有正在玩的玩家的剩余筹码数量", tableData.TableId);
				Tool.WriteLine("广播20020桌子中所有正在玩的玩家的剩余筹码数量");
				tableData.IsHavaSendCards = true;
			});
			System.Threading.Thread.Sleep(300);

			//给单独每个玩家发送自己的两张手牌
			foreach (var playerPos in readyPosition)
			{
				var cardData = playerPos.CardData;
				var cardParam = new Parameters();
				cardParam["TableId"] = tableData.TableId;
				cardParam["PosId"] = playerPos.Id;
				var cardStr = Convert.ToBase64String(ProtoBufUtils.Serialize(cardData));
				cardParam["Cards"] = cardStr;
				var player = playerPos.CurrentGameUser();
				if (player != null)
				{
					//添加每个人的手牌到当前局玩家手牌记录
					if (!tableData.AddCurrentUserCards(new KeyValuePair<SimpleUserData, List<int>>(new SimpleUserData() { UserId = playerPos.UserId, HeadIcon = playerPos.HeadIcon, NickName = playerPos.NickName }, cardData)))
					{
						Tool.WriteErrorLine("玩家手牌添加出错");
					}
					SyncNotifyAction((int)ActionType.DZBrocastPlayerCards, player, cardParam, t =>
					{
						TraceLog.WriteComplement("广播消息30004 发送每个玩家的手牌桌子:{0} 座位:{1}发牌成功", tableData.TableId, player.Property.GetPositionId(tableData.TableId));
					});
				}
				else
				{
					Console.WriteLine("没有找到id为:{0}的玩家", player.GetUserId());
				}
			}

			//广播每个玩家的牌型
			Tool.WriteErrorLine("广播发完两张手牌的牌型");
			BroadcastPlayersCardType(tableData);
			System.Threading.Thread.Sleep(300);

			#region 起手手牌判断类型
			//TODO:判断手牌类型，并且判断是否触发保险，如果没有触发则NextBet，如果触发了则按照触发的流程来，一开始的三张牌单独发放
			//var cardDatas = new List<List<int>>();
			//foreach(var playerPos in readyPosition)
			//{
			//	cardDatas.Add(playerPos.CardData);
			//}
			//var resultCardDatas = _cardRole.CombineMinFiveCards(cardDatas, 2, tableData.BackUpCardData);  //所有玩家变成最小的五张牌，好做比较
			#endregion

			//继续轮流下注
			this.NextBet(tableData);
		}

		/// <summary>
		/// 检查开局
		/// </summary>
		/// <param name="tableData"></param>
		public void CheckStart(TableData tableData)
		{
			if (tableData.TableReadyStart == false)
			{
				Tool.WriteWarmingLine("等待房主开局");
				return;
			}
			//数据重置
			tableData.TableDataReset();
			//延时两秒
			//System.Threading.Thread.Sleep(2000);
			tableData.State = TableState.WaitCheck;
			tableData.ReStartTimer(tableData.CheckStartTime);
		}

		private void CheckStartCallBack(TableData tableData)
		{
			var readyPosition = tableData.GetCurrentGetReadyPosition();
			if (!tableData.IsHavaSendCards)
			{
				//判断房间是否开局或者是否满足>2的条件
				if (readyPosition.Count >= 2 && !tableData.Pause)
				{
					foreach (var pos in readyPosition)
					{
						pos.PlayState = PositionPlayState.Play;
					}

					tableData.State = TableState.Countdown;
					var leftTime = tableData.ChipMoveTimeToTablePool;
					//广播开局消息
					var startGameParam = new Parameters();
					startGameParam["TableID"] = tableData.TableId;
					SyncNotifyAction((int)ActionType.DZGameStart, tableData, startGameParam, t =>
					{
						TraceLog.WriteComplement("广播消息30010 桌子{0}开始游戏", tableData.TableId);
					});
					System.Threading.Thread.Sleep(500);
					//启动定时器，开始到实际
					tableData.ReStartTimer(leftTime);
					//广播倒计时
					var param = new Parameters();
					param["TableID"] = tableData.TableId;
					param["LeftTime"] = (int)(leftTime / 1000);
					SyncNotifyAction((int)ActionType.DZGameStartCountDown, tableData, param, t =>
					{
						TraceLog.WriteComplement("广播消息30011 桌子{0}开始游戏倒计时", tableData.TableId);
					});
				}
				//如果人数不满足则进入等待状态
				else
				{
					Tool.WriteErrorLine("不足两个人,进入等待状态, 或者是牌局暂停");
					tableData.State = TableState.Waiting;
					var param = new Parameters();
					param["TableId"] = tableData.TableId;
					//发送消息告知所有人桌子在等待玩家进入
					SyncNotifyAction((int)ActionType.DZBroadCastTableIsInWaitingState, tableData, param, t =>
					{
						TraceLog.WriteComplement("桌子:{0}进入等待玩家的状态，或者因为牌局暂停", tableData.TableId);
					});
				}
			}
		}

		//************************************************************新的游戏逻辑*********************************/
		/// <summary>
		/// 游戏结束
		/// </summary>
		/// <returns></returns>
		private bool OnEventGameConclude(TableData tableData, GameOverType overType = GameOverType.Normal)
		{
			switch (overType)
			{
				//正常退出
				case GameOverType.Normal:
					{
						GameEnd gameEnd = new GameEnd();
						gameEnd.TotalEnd = 1;
						List<PositionData> playDataPos = new List<PositionData>();
						//剔除掉弃牌的玩家
						foreach (var pos in tableData.CurrentPlayingPositionData)
						{
							if (pos.PlayState != PositionPlayState.Fold)
								playDataPos.Add(pos);
						}
						var playerCount = playDataPos.Count;
						try
						{
							Tool.WriteWarmingLine("游戏正常结束，进入七张牌选五张最优比牌逻辑");
							for (int i = 0; i < playerCount; i++)
							{
								var posData = tableData.CurrentPlayingPositionData[i];
								//排除弃牌玩家
								if (posData.PlayState == PositionPlayState.Fold)
									continue;
								var lastCardData = new int[this._cardRole.MAX_CENTERCOUNT];
								//最大牌型
								var endCardType = this._cardRole.FiveFromOther(posData.CardData.ToArray(), this._cardRole.MAX_COUNT, tableData.BackCardData.ToArray(), this._cardRole.MAX_CENTERCOUNT, ref lastCardData, this._cardRole.MAX_CENTERCOUNT);
								if (endCardType == DeckType.None)
								{
									Tool.WriteErrorLine("获得牌型错误");
									return false;
								}
								gameEnd.LastCenterCardData.Add(lastCardData);
							}
						}
						catch (Exception ex)
						{
							Tool.WriteErrorLine(ex.ToString());
						}

						//总下注备份
						List<int> totalScore = new List<int>();
						totalScore.AddRange(tableData.TotalScore);

						//胜利列表
						List<UserWinList> winnerList = new List<UserWinList>();

						//临时保存的最后没有弃牌玩家的最大牌数组
						var tempCardDataList = new List<int[]>();
						tempCardDataList.AddRange(gameEnd.LastCenterCardData);

						int winCount = 0;
						try
						{
							//用户得分顺序
							for (int i = 0; i < playerCount; i++)
							{
								UserWinList winner = new UserWinList();
								winnerList.Add(winner);
								//查找最大用户,如果没有的话就进入内部直接这个玩家
								if (!this._cardRole.SelectMaxUser(tempCardDataList, ref winner, ref totalScore))
								{
									winCount = i;
									break;
								}

								//删除胜利数据
								for (int j = 0; j < winnerList[i].SameCount; j++)
								{
									var removeIndex = winnerList[i].WinerList[j];
									if (tempCardDataList[removeIndex][0] == 0)
									{
										Tool.WriteErrorLine("不应该为0");
										return false;
									}
									//清空数组
									Array.Clear(tempCardDataList[removeIndex], 0, tempCardDataList[removeIndex].Length);
								}
							}
						}
						catch (Exception ex)
						{
							Tool.WriteErrorLine("选择最大用户错误");
							Tool.WriteErrorLine(ex.ToString());
						}

						//强退用户
						for (int i = 0; i < playerCount; i++)
						{
							if (playDataPos[i].PlayState == PositionPlayState.Fold && totalScore[i] > 1)
							{
								winnerList[winCount].WinerList[winnerList[winCount].SameCount++] = i;
							}
						}

						var userScore = new int[9];
						try
						{
							for (int i = 0; i < playerCount - 1; i++)
							{
								var iWinCount = winnerList[i].SameCount;
								if (iWinCount == 0)
									break;

								//胜利用户得分情况
								for (int j = 0; j < iWinCount; j++)
								{
									var tempPosIndex = winnerList[i].WinerList[j];
									var posData = tableData.CurrentPlayingPositionData[tempPosIndex];
									if (posData == null)
									{
										Tool.WriteErrorLine("胜利用户得分情况获取位置失败");
										return false;
									}
									var posIndex = posData.Id - 1; //从0开始的位置索引
									if (totalScore[posIndex] == 0)   //totalscore 就个玩家下注的总筹码
										continue;
									var posIndex2 = 0;
									if (j > 0)
									{
										tempPosIndex = winnerList[i].WinerList[j - 1];
										if (tempPosIndex > 8 || tempPosIndex < 0)
										{
											Tool.WriteErrorLine("胜利用户得分情况位置不合法   位置索引:" + tempPosIndex);
											return false;
										}
										posData = tableData.CurrentPlayingPositionData[tempPosIndex];
										if (posData == null)
										{
											Tool.WriteErrorLine("胜利用户得分情况获取位置2失败");
											return false;
										}
										posIndex2 = posData.Id - 1;
										if (totalScore[posIndex] - totalScore[posIndex2] == 0)
											continue;
									}
									//失败用户失分情况
									for (int k = i + 1; k < playerCount; k++)
									{
										//失败人数
										if (0 == winnerList[k].SameCount)
											break;
										for (int l = 0; l < winnerList[k].SameCount; l++)
										{
											posData = tableData.CurrentPlayingPositionData[winnerList[k].WinerList[l]];
											if (posData == null)
											{
												Tool.WriteErrorLine("胜利用户得分情况获取位置3失败");
												return false;
											}
											var posIndex3 = posData.Id - 1;
											//用户已赔空
											if (0 == totalScore[posIndex3])
												continue;

											var lostIndex = posIndex3;
											var winIndex = posIndex;
											var minScore = 0;

											//上家得分数目
											var lastScore = ((j > 0) ? totalScore[posIndex2] : 0);
											if (j > 0)
											{
												if (lastScore <= 0)
												{
													Tool.WriteErrorLine("断言 上架得分分数有问题");
													return false;
												}
											}
											minScore = Math.Min(totalScore[winIndex] - lastScore, totalScore[lostIndex]);

											for (int m = j; m < iWinCount; m++)
											{
												tempPosIndex = winnerList[i].WinerList[m];
												if (tempPosIndex > 8 || tempPosIndex < 0)
												{
													Tool.WriteErrorLine("胜利用户得分情况位置4不合法   位置索引:" + tempPosIndex);
													return false;
												}
												posData = tableData.CurrentPlayingPositionData[tempPosIndex];
												if (posData == null)
												{
													Tool.WriteErrorLine("胜利用户得分情况获取位置4失败");
													return false;
												}
												var posIndex4 = posData.Id - 1;
												//得分数目
												userScore[posIndex4] += minScore / (iWinCount - j);
											}

											//赔偿数目
											userScore[lostIndex] -= minScore;
											totalScore[lostIndex] -= minScore;
										}
									}
								}
							}
						}
						catch (Exception ex)
						{
							Tool.WriteErrorLine(ex.ToString());
						}

						//统计用户分数
						for (int i = 0; i < playerCount; i++)
						{
							var posData = tableData.CurrentPlayingPositionData[i];
							if (posData == null)
							{
								Tool.WriteErrorLine("统计用户分数失败");
								return false;
							}
							var tempPosIndex = posData.Id - 1;
							gameEnd.GameScore[tempPosIndex] = userScore[tempPosIndex];
							if (userScore[tempPosIndex] + tableData.TotalScore[tempPosIndex] < 0)
							{
								Tool.WriteErrorLine("断言 统计用户分数错误");
								return false;
							}
							if (gameEnd.GameScore[tempPosIndex] > 0)
							{
								gameEnd.GameTax[tempPosIndex] = 0;  //不计算税收
								gameEnd.GameScore[tempPosIndex] -= gameEnd.GameTax[tempPosIndex];
							}
						}
						//添加摊牌率
						foreach (var pos in tableData.CurrentPlayingPositionData)
						{
							if (pos.PlayState != PositionPlayState.Fold)
								tableData.AddShowCardsCount(pos.UserId);
						}

						//如果只有一个胜利的玩家，则给这个玩家统计胜利次数
						var firstWinner = winnerList[0];
						if (firstWinner != null && firstWinner.SameCount == 1)
						{
							var tempPosIndex = firstWinner.WinerList[0];
							if (tempPosIndex > 8 || tempPosIndex < 0)
							{
								Tool.WriteErrorLine("胜利用户得分情况位置4不合法   位置索引:" + tempPosIndex);
								return false;
							}
							var posData = tableData.CurrentPlayingPositionData[tempPosIndex];
							if (posData == null)
							{
								Tool.WriteErrorLine("胜利用户得分情况获取位置失败");
								return false;
							}
							tableData.AddWinnerCount(posData.UserId);
							tableData.AddShowCardsAndWinCount(posData.UserId);
						}

						var param = new Parameters();
						param["TableId"] = tableData.TableId;
						var usersWinChip = new List<UsersWinGetChip>();
						//结算获胜筹码
						for (int i = 0; i < playerCount; i++)
						{
							var posData = tableData.CurrentPlayingPositionData[i];
							if (posData == null)
							{
								Tool.WriteErrorLine("统计用户分数失败");
								return false;
							}
							if (posData.PlayState == PositionPlayState.Fold)
							{
								//如果弃牌的话直接跳过
								Tool.WriteWarmingLine(string.Format("玩家{0}已经弃牌，不参与结算", posData.Id));
								continue;
							}
							var tempPosIndex = posData.Id - 1;
							//胜利的玩家获得的筹码
							if (gameEnd.GameScore[tempPosIndex] >= 0)
							{
								var getChip = tableData.TotalScore[tempPosIndex] + gameEnd.GameScore[tempPosIndex];
								posData.Chip += getChip;

								if (tableData.Insurance)
								{
									//posData.Chip += tableData.InsureChip[tempPosIndex];
									foreach (var pool in tableData.InsurancePool)
									{
										posData.Chip += tableData.GetUserTotalInsuranceCompansate(posData.UserId);
										//TODO:要减去当前购买保险的筹码
										posData.Chip -= tableData.GetUserTotalUseInInsurance(posData.UserId);
									}
								}

								var userWinChip = new UsersWinGetChip() { UserId = posData.UserId, PosId = posData.Id, Chip = getChip, TotalChip = posData.Chip };
								usersWinChip.Add(userWinChip);
							}
							else
							{
								//如果还有结余的余额也添加到当前玩家的筹码中
								if (totalScore[tempPosIndex] > 0)
								{
									var winChip = totalScore[tempPosIndex];
									if (tableData.Insurance)
									{
										//posData.Chip += tableData.InsureChip[tempPosIndex];
										foreach (var pool in tableData.InsurancePool)
										{
											posData.Chip += tableData.GetUserTotalInsuranceCompansate(posData.UserId);
											//TODO:要减去当前购买保险的筹码
											posData.Chip -= tableData.GetUserTotalUseInInsurance(posData.UserId);
										}
									}
									posData.Chip += winChip;
									var userWinChip = new UsersWinGetChip() { UserId = posData.UserId, PosId = posData.Id, Chip = winChip, TotalChip = posData.Chip };
									usersWinChip.Add(userWinChip);
								}
							}
						}
						//保存保险人的筹码数量
						foreach (var pool in tableData.InsurancePool)
						{
							tableData.TableInsurer.Chip += tableData.InsurancerWin;
							tableData.AddCurrentUserScore(new SharedUserInTableHandScore() { TableID = tableData.TableLogicID, Hand = tableData.HandVersionID, Insurance = true, Profit = tableData.TableInsurer.Chip, UserID = tableData.InsureId });
						}

						foreach (var pos in tableData.CurrentPlayingPositionData)
						{
							//判断是否在胜利列表里,如果不在的话,则当前下注的筹码都是输掉的筹码
							bool isWin = false;
							foreach (var userWin in usersWinChip)
							{
								if (pos.UserId == userWin.UserId)
								{
									isWin = true; //胜利的玩家
									//tableData.UserInTableHandScoreList.Add(new SharedUserInTableHandScore() { TableID = tableData.TableLogicID, Hand = tableData.HandVersionID, Insurance = false, Profit = userWin.Chip, UserID = pos.UserId });
									tableData.AddCurrentUserScore(new SharedUserInTableHandScore() { TableID = tableData.TableLogicID, Hand = tableData.HandVersionID, Insurance = false, Profit = userWin.Chip - pos.CurrentHandBetChip, UserID = pos.UserId });
									break;
								}
							}
							if (!isWin)  //输掉的玩家
							{
								//tableData.UserInTableHandScoreList.Add(new SharedUserInTableHandScore() { TableID = tableData.TableLogicID, Hand = tableData.HandVersionID, Insurance = false, Profit = -pos.CurrentHandBetChip, UserID = pos.UserId });
								tableData.AddCurrentUserScore(new SharedUserInTableHandScore() { TableID = tableData.TableLogicID, Hand = tableData.HandVersionID, Insurance = false, Profit = -pos.CurrentHandBetChip, UserID = pos.UserId });
							}
						}

						foreach (var score in tableData.currentUsersScore)
						{
							tableData.UserInTableHandScoreList.Add(new SharedUserInTableHandScore() { TableID = score.TableID, Hand = score.Hand, Insurance = score.Insurance, Profit = score.Profit, UserID = score.UserID });
						}


						param["UsersWinChip"] = Convert.ToBase64String(ProtoBufUtils.Serialize(usersWinChip));
						tableData.AnteNum = 0;
						param["AntNum"] = tableData.AnteNum;  //当前底池的筹码数量

						SyncNotifyAction((int)ActionType.DZBrocastChipSettlement, tableData, param, t =>
						{
							Tool.WriteLine("30016消息广播玩家获得的筹码");
						});

						System.Threading.Thread.Sleep(tableData.ChipMoveTimeToTablePool);
						this.GameOver(tableData);
					}
					break;
				//没有玩家
				case GameOverType.NoPlayer:
					{

					}
					break;
				//用户离开
				case GameOverType.UserLeave:
				//网络错误
				case GameOverType.NetError:
					{

					}
					break;
			}
			return true;
		}

		public bool OnUserBet(TableData table, int tableId, int chip, PositionData positionData)
		{
			Tool.WriteWarmingLine(string.Format("位置{0}下注:{1}", positionData.Id, positionData.PlayState));
			positionData.BetState = false;
			table.StopTimer();

			//记录玩家下注的类型
			//if (table.GTableData != null)
			//{
			//	if (table.GTableData.TableID == 0)
			//	{
			//		table.GTableData.TableID = this.GetGameTableDataNextNo();
			//	}
			//var userBetRecordsId = this.UserBetRecordId + this.userBetRecordNextNo;
			//Tools.Tool.WriteErrorLine("玩家下注记录ID:" + userBetRecordsId);
			//table.AddUserBetRecords(new UserBetRecord() { ID = userBetRecordsId, UserID = positionData.UserId, TableID = table.GTableData.TableID, BetType = (int)positionData.PlayState, BetNum = chip });
			//table.AddUserBetRecordInCurrent(new NewUserBetRecord() { TableID = table.TableLogicID, UserID = positionData.UserId, UserName = positionData.NickName, UserHeadIcon = positionData.HeadIcon, Round = table.Round, BetType = ((int)positionData.PlayState).ToEnumDescriptionString(typeof(PositionPlayState)), BetNum = chip });
			table.AddUserBetRecordInCurrent(new SharedUserBetRecord() { TableID = table.TableLogicID, UserID = positionData.UserId, Round = table.Round, Hand = table.HandVersionID, BetType = ((int)positionData.PlayState).ToEnumDescriptionString(typeof(PositionPlayState)), BetNum = chip });
			//添加玩家下注的Log记录
			//table.AddUserBetRecordLog(new LogUserBetRecord() { TableID = table.TableId, UserID = positionData.UserId, UserName = positionData.NickName, UserHeadIcon = positionData.HeadIcon, Round = table.Round, BetType = ((int)positionData.PlayState).ToEnumDescriptionString(typeof(PositionPlayState)), BetNum = chip });
			//}
			//else
			//	Tool.WriteErrorLine("桌子编号不存在");

			//设置当前MaxUserPosId和Max
			var betChip = chip + positionData.CurrentRoundChip;
			if (table.CurrentMaxChipPosId == -1 || betChip > table.CurrentMaxChip)
			{
				table.SetCurrentMaxChip(betChip);
				table.SetCurrentMaxChipPosId(positionData.Id);
			}
			//记录上一次下注非AllIn的位置
			if (positionData.PlayState != PositionPlayState.AllIn && positionData.PlayState != PositionPlayState.Fold)
				table.FormalNormalOperatePosID = positionData.Id;

			//如果玩家主动加筹码则记录入局
			if (positionData.PlayState == PositionPlayState.Add || positionData.PlayState == PositionPlayState.AllIn || positionData.PlayState == PositionPlayState.Follow)
				table.AddEnterTableCount(positionData.UserId);



			//翻牌前加注也就是第0个回合的时候加注
			if (positionData.PlayState == PositionPlayState.Add)
			{
				if (table.Round == 0)
				{
					table.AddChipBeforeShowCardCount(positionData.UserId);
				}
			}

			positionData.CurrentRoundChip += chip;
			positionData.CurrentHandBetChip += chip;
			//记录上一次的位置
			table.FormalOperatePosId = positionData.Id;
			//记录玩家下注
			table.SetBetRecord(table.Round, positionData.Id, chip);

			var parameters = new Parameters();
			parameters["TableID"] = tableId;
			parameters["UserID"] = positionData.UserId;
			parameters["PosID"] = positionData.Id;
			parameters["Chip"] = positionData.CurrentRoundChip;  //显示当前回合下注的总数量
			parameters["BetType"] = (int)positionData.PlayState;
			parameters["LeftChip"] = positionData.Chip;
			SyncNotifyAction((int)ActionType.DZBrocastPlayBetChoose, table, parameters, t =>
			{
				TraceLog.WriteComplement("广播30008玩家下注操作", table.TableId, positionData.Id);
			});

			System.Threading.Thread.Sleep(table.ChipMoveTime);
			return true;
		}

		/// <summary>
		/// 放弃事件
		/// </summary>
		/// <param name="tableData">桌子</param>
		/// <param name="posId">座位ID</param>
		/// <param name="forceLeft">是否被强退</param>
		/// <returns></returns>
		public void OnUserGiveUp(TableData tableData, int posId, bool forceLeft = false)
		{
			try
			{
				//重置状态
				var pos = tableData.Positions[posId - 1];
				pos.PlayState = PositionPlayState.Fold;
				pos.MaxBet = false;

				//要将正在玩的数组里面去掉
				//tableData.RemoveFoldPosition(pos);

				//如果当前已经发了三张牌了则添加统计
				if (tableData.Round > 1)
					tableData.AddForgiveByThreeBETCount(pos.UserId);

				//判断当前是不是就剩一个人，其他人都弃牌了
				if (tableData.OtherPlayersAreAllFoldExceptOne())
				{
					var winnnerPos = tableData.GetWinner();
					GameTable.Current.CollectChip(tableData);
					//直接进入分成
					GameTable.Current.ChipSettlement(tableData, ChipSettlementType.Fold, GameTable.Current.CheckStart);
					return;
				}
				tableData.StopTimer();
				//继续下一个玩家
				GameTable.Current.NextBet(tableData);
			}
			catch (Exception ex)
			{
				Tool.WriteErrorLine(string.Format("玩家弃牌有异常：{0}", ex.ToString()));
			}
		}

		/// <summary>
		/// 断线处理事件
		/// </summary>
		/// <param name="userId"></param>
		public void OnDisconnect(int userId)
		{
			var _currentGameUser = GameTable.Current.GetUser(userId);
			if (_currentGameUser == null)
			{
				Tool.WriteWarmingLine("断线处理的玩家不存在");
				return;
			}
			Tool.WriteErrorLine("玩家下线，桌子要将他信息移除:" + userId);
			var tableIdList = _currentGameUser.Property.TableIdList;
			foreach (var tableId in tableIdList)
			{
				var _currentTable = GameRoom.Current.GetTableData(tableId);
				if (_currentTable == null)
				{
					Tool.WriteWarmingLine("断线处理的玩家所在的桌子不存在");
					return;
				}
				if (_currentGameUser.Property.GetPositionId(tableId) >= 1 && _currentGameUser.Property.GetPositionId(tableId) <= 9)
				{
					//清空数据
					var posData = _currentTable.Positions[_currentGameUser.Property.GetPositionId(tableId) - 1];
					if (posData == null)
					{
						Tool.WriteErrorLine("处理玩家断线，没有找到当前玩家的位置:" + _currentGameUser.Property.GetPositionId(tableId));
						return;
					}
					_currentGameUser.Property.Clear(tableId);
				}
				else
				{
					Tool.WriteWarmingLine(string.Format("玩家位置{0}不对，不需要删除信息", _currentGameUser.Property.GetPositionId(tableId)));
				}
			}
		}
	}
}
